From f2db1331539ade5575937b54bec0141f4d4233b6 Mon Sep 17 00:00:00 2001 From: Aaron Cuevas Lopez Date: Sun, 13 Oct 2024 03:55:54 +0200 Subject: [PATCH 1/7] Add static functions to configure DS90UB933/931 serializer links --- OpenEphys.Onix1/DS90UB9x.cs | 58 +++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/OpenEphys.Onix1/DS90UB9x.cs b/OpenEphys.Onix1/DS90UB9x.cs index 56a2eca0..bc0f55dd 100644 --- a/OpenEphys.Onix1/DS90UB9x.cs +++ b/OpenEphys.Onix1/DS90UB9x.cs @@ -1,4 +1,6 @@ -namespace OpenEphys.Onix1 +using System; + +namespace OpenEphys.Onix1 { static class DS90UB9x { @@ -29,6 +31,28 @@ static class DS90UB9x // unmanaged default serializer / deserializer I2C addresses public const uint DES_ADDR = 0x30; public const uint SER_ADDR = 0x58; + + internal static void Initialize933SerDesLink(DeviceContext device, DS90UB9xMode dataMode) //also valid for 913 + { + var deserializer = new I2CRegisterContext(device, DES_ADDR); + deserializer.WriteByte((uint)DS90UB934DeserializerI2CRegister.PortSel, 0x01); //Enable port 0 + deserializer.WriteByte((uint)DS90UB934DeserializerI2CRegister.PortMode, 0x4 + (uint)dataMode); //0x4 maintains coax mode + deserializer.WriteByte((uint)DS90UB934DeserializerI2CRegister.I2CConfig, 0b01011000); //7: i2c pass all (0), 6: i2c pass (1), 5: auto_ack (0), 4: BC enable (1), 3: BC crc en (1), 2: reserved (0) 1:0: bc freq (00) 2.5Mbps + deserializer.WriteByte((uint)DS90UB934DeserializerI2CRegister.SerAlias, SER_ADDR << 1); + //Enable backchannel GPIO on deserializer. It is then the serializer task to decide if using them or use manual output + deserializer.WriteByte((uint)DS90UB934DeserializerI2CRegister.GpioCtrl0, 0x10); + deserializer.WriteByte((uint)DS90UB934DeserializerI2CRegister.GpioCtrl0, 0x32); + } + + internal static void Set933I2CRate(DeviceContext device, double i2cRate) + { + var serializer = new I2CRegisterContext(device, SER_ADDR); + double SCLtimes = (1.0 / (100e-9 * i2cRate)); + uint SCLvalir = (uint)Math.Round(SCLtimes); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.SCLHIGH, SCLvalir); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.SCLLOW, SCLvalir); + } + } enum DS90UB9xTriggerMode : uint @@ -65,6 +89,12 @@ enum DS90UB9xMarkMode : uint enum DS90UB9xDeserializerI2CRegister { PortMode = 0x6D, + PortSel = 0x4C, + I2CConfig = 0x58, + GpioCtrl0 = 0x6E, + GpioCtrl1 = 0x6F, + + SerAlias = 0x5C, SlaveID1 = 0x5E, SlaveID2 = 0x5F, @@ -83,12 +113,28 @@ enum DS90UB9xDeserializerI2CRegister SlaveAlias7 = 0x6C, } - enum DS90UB9xSerializerI2CRegister +// enum DS90UB9xSerializerI2CRegister +// { +// GPIO10 = 0x0D, +// GPIO32 = 0x0E, +// SCLHIGH = 0x0A, +// SCLLOW = 0x0B +// } + + enum DS90UB933SerializerI2CRegister { GPIO10 = 0x0D, GPIO32 = 0x0E, - SCLHIGH = 0x0A, - SCLLOW = 0x0B + SCLHIGH = 0x11, + SCLLOW = 0x12 + } + + enum DS90UB953SerializerI2CRegister + { + GPIO_DATA = 0x0D, + GPIO_IO_CTRL = 0x0E, + SCLHIGH = 0x0B, + SCLLOW = 0x0C } enum DS90UB9xMode @@ -102,5 +148,7 @@ enum DS90UB9xDirection { Input = 0, Output = 1 - } + } + + } From bced02bda41e6802d96b3c6f2a81fc1db5e7a0d3 Mon Sep 17 00:00:00 2001 From: Aaron Cuevas Lopez Date: Sun, 13 Oct 2024 21:27:22 +0200 Subject: [PATCH 2/7] Fixes on miniscope configuration - I2C access using new addressing and initialization - Set a I2C speed of 80KHz, arbitraty but proven to work - Tweaked initialization delays --- OpenEphys.Onix1/ConfigureUclaMiniscopeV4.cs | 2 ++ .../ConfigureUclaMiniscopeV4Camera.cs | 25 +++++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/OpenEphys.Onix1/ConfigureUclaMiniscopeV4.cs b/OpenEphys.Onix1/ConfigureUclaMiniscopeV4.cs index 6ff9ba76..7b77cda0 100644 --- a/OpenEphys.Onix1/ConfigureUclaMiniscopeV4.cs +++ b/OpenEphys.Onix1/ConfigureUclaMiniscopeV4.cs @@ -158,6 +158,7 @@ override protected bool CheckLinkState(DeviceContext device) const int FailureToWriteRegister = -6; try { + ConfigureUclaMiniscopeV4Camera.ConfigureSerializer(ds90ub9x); ConfigureUclaMiniscopeV4Camera.ConfigureCameraSystem(ds90ub9x, Camera.FrameRate, Camera.InterleaveLed); } catch (ONIException ex) when (ex.Number == FailureToWriteRegister) @@ -165,6 +166,7 @@ override protected bool CheckLinkState(DeviceContext device) return false; } + Thread.Sleep(150); var linkState = device.ReadRegister(PortController.LINKSTATE); return (linkState & PortController.LINKSTATE_SL) != 0; } diff --git a/OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs b/OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs index bd783856..ef3a82e6 100644 --- a/OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs +++ b/OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs @@ -190,15 +190,10 @@ internal static void ConfigureDeserializer(DeviceContext device) // acquisition. For this reason, the frame start needs to be marked. device.WriteRegister(DS90UB9x.MARK, (uint)DS90UB9xMarkMode.VsyncRising); - // set I2C clock rate to ~100 kHz - var deserializer = new I2CRegisterContext(device, DS90UB9x.DES_ADDR); - deserializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.SCLHIGH, 0x7A); - deserializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.SCLLOW, 0x7A); - - // configure deserializer I2C aliases - uint coaxMode = 0x4 + (uint)DS90UB9xMode.Raw12BitLowFrequency; // 0x4 maintains coax mode - deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.PortMode, coaxMode); + DS90UB9x.Initialize933SerDesLink(device, DS90UB9xMode.Raw12BitLowFrequency); + var deserializer = new I2CRegisterContext(device, DS90UB9x.DES_ADDR); + uint i2cAlias = UclaMiniscopeV4.AtMegaAddress << 1; deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveID1, i2cAlias); deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveAlias1, i2cAlias); @@ -210,6 +205,16 @@ internal static void ConfigureDeserializer(DeviceContext device) i2cAlias = UclaMiniscopeV4.Max14574Address << 1; deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveID3, i2cAlias); deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveAlias3, i2cAlias); + + // set I2C clock rate to ~100 kHz + var serializer = new I2CRegisterContext(device, DS90UB9x.SER_ADDR); + serializer.WriteByte((uint)0x11, 0x7A); + serializer.WriteByte((uint)0x12, 0x7A); + } + + internal static void ConfigureSerializer(DeviceContext device) + { + DS90UB9x.Set933I2CRate(device, 80e3); //This is an arbitrary value that is proven to work, we need to test speed vs reliability vs bno sampling speed } internal static void ConfigureCameraSystem(DeviceContext device, UclaMiniscopeV4FramesPerSecond frameRate, bool interleaveLed) @@ -219,9 +224,9 @@ internal static void ConfigureCameraSystem(DeviceContext device, UclaMiniscopeV4 // set up Python480 var atMega = new I2CRegisterContext(device, UclaMiniscopeV4.AtMegaAddress); WriteCameraRegister(atMega, 16, 3); // Turn on PLL - Thread.Sleep(WaitUntilPllSettles); + //Thread.Sleep(WaitUntilPllSettles); //This sometimes has good effects, sometimes adverse, we just might want to redo this entire section (see issue #331 ) WriteCameraRegister(atMega, 32, 0x7007); // Turn on clock management - Thread.Sleep(WaitUntilPllSettles); + //Thread.Sleep(WaitUntilPllSettles); WriteCameraRegister(atMega, 199, 666); // Defines granularity (unit = 1/PLL clock) of exposure and reset_length WriteCameraRegister(atMega, 200, 3300); // Set frame rate to 30 Hz WriteCameraRegister(atMega, 201, 3000); // Set Exposure From d9832ac9b59b1d842f18ce537c7ff23069bc5077 Mon Sep 17 00:00:00 2001 From: Aaron Cuevas Lopez Date: Sun, 13 Oct 2024 21:36:25 +0200 Subject: [PATCH 3/7] Fix naming on DS90UBx file caused by ongoing work --- OpenEphys.Onix1/DS90UB9x.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenEphys.Onix1/DS90UB9x.cs b/OpenEphys.Onix1/DS90UB9x.cs index bc0f55dd..48e56b1e 100644 --- a/OpenEphys.Onix1/DS90UB9x.cs +++ b/OpenEphys.Onix1/DS90UB9x.cs @@ -35,13 +35,13 @@ static class DS90UB9x internal static void Initialize933SerDesLink(DeviceContext device, DS90UB9xMode dataMode) //also valid for 913 { var deserializer = new I2CRegisterContext(device, DES_ADDR); - deserializer.WriteByte((uint)DS90UB934DeserializerI2CRegister.PortSel, 0x01); //Enable port 0 - deserializer.WriteByte((uint)DS90UB934DeserializerI2CRegister.PortMode, 0x4 + (uint)dataMode); //0x4 maintains coax mode - deserializer.WriteByte((uint)DS90UB934DeserializerI2CRegister.I2CConfig, 0b01011000); //7: i2c pass all (0), 6: i2c pass (1), 5: auto_ack (0), 4: BC enable (1), 3: BC crc en (1), 2: reserved (0) 1:0: bc freq (00) 2.5Mbps - deserializer.WriteByte((uint)DS90UB934DeserializerI2CRegister.SerAlias, SER_ADDR << 1); + deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.PortSel, 0x01); //Enable port 0 + deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.PortMode, 0x4 + (uint)dataMode); //0x4 maintains coax mode + deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.I2CConfig, 0b01011000); //7: i2c pass all (0), 6: i2c pass (1), 5: auto_ack (0), 4: BC enable (1), 3: BC crc en (1), 2: reserved (0) 1:0: bc freq (00) 2.5Mbps + deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SerAlias, SER_ADDR << 1); //Enable backchannel GPIO on deserializer. It is then the serializer task to decide if using them or use manual output - deserializer.WriteByte((uint)DS90UB934DeserializerI2CRegister.GpioCtrl0, 0x10); - deserializer.WriteByte((uint)DS90UB934DeserializerI2CRegister.GpioCtrl0, 0x32); + deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.GpioCtrl0, 0x10); + deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.GpioCtrl0, 0x32); } internal static void Set933I2CRate(DeviceContext device, double i2cRate) From fcf84e7f5d6f4f0c72ca7307b8d53b565e0f406d Mon Sep 17 00:00:00 2001 From: Aaron Cuevas Lopez Date: Sun, 13 Oct 2024 21:36:35 +0200 Subject: [PATCH 4/7] Update I2C accesses on Neuropixel devices - Use the specific serializer enum for serializer addresses - Use the DS90UB9x static method to set i2c speed - Use the DS90UB9x static methos for serdes link initialization --- OpenEphys.Onix1/ConfigureNeuropixelsV1e.cs | 17 ++++++------- OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs | 19 +++++++------- .../ConfigureNeuropixelsV2eBeta.cs | 25 +++++++++---------- 3 files changed, 29 insertions(+), 32 deletions(-) diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV1e.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV1e.cs index 353e6183..39541a95 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV1e.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV1e.cs @@ -141,8 +141,7 @@ public override IObservable Process(IObservable source var serializer = new I2CRegisterContext(device, DS90UB9x.SER_ADDR); // set I2C clock rate to ~400 kHz - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.SCLHIGH, 20); - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.SCLLOW, 20); + DS90UB9x.Set933I2CRate(device, 400e3); // read probe metadata var probeMetadata = new NeuropixelsV1eMetadata(serializer); @@ -167,8 +166,8 @@ public override IObservable Process(IObservable source var deviceInfo = new NeuropixelsV1eDeviceInfo(context, DeviceType, deviceAddress, probeControl); var shutdown = Disposable.Create(() => { - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO10, NeuropixelsV1e.DefaultGPO10Config); - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO32, NeuropixelsV1e.DefaultGPO32Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, NeuropixelsV1e.DefaultGPO10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, NeuropixelsV1e.DefaultGPO32Config); }); return new CompositeDisposable( DeviceManager.RegisterDevice(deviceName, deviceInfo), @@ -194,10 +193,10 @@ static void ConfigureDeserializer(DeviceContext device) device.WriteRegister(DS90UB9x.DATALINES0, 0x3245106B); // Sync, psb[0], psb[1], psb[2], psb[3], psb[4], psb[5], psb[6], device.WriteRegister(DS90UB9x.DATALINES1, 0xFFFFFFFF); + DS90UB9x.Initialize933SerDesLink(device, DS90UB9xMode.Raw12BitHighFrequency); + // configure deserializer I2C aliases var deserializer = new I2CRegisterContext(device, DS90UB9x.DES_ADDR); - uint coaxMode = 0x4 + (uint)DS90UB9xMode.Raw12BitHighFrequency; // 0x4 maintains coax mode - deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.PortMode, coaxMode); uint alias = NeuropixelsV1e.ProbeAddress << 1; deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveID1, alias); @@ -211,16 +210,16 @@ static void ConfigureDeserializer(DeviceContext device) static void ResetProbe(I2CRegisterContext serializer, uint gpo10Config) { gpo10Config &= ~NeuropixelsV1e.Gpo10ResetMask; - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); Thread.Sleep(1); gpo10Config |= NeuropixelsV1e.Gpo10ResetMask; - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); } static uint TurnOnLed(I2CRegisterContext serializer, uint gpo23Config) { gpo23Config &= ~NeuropixelsV1e.Gpo32LedMask; - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO32, gpo23Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, gpo23Config); return gpo23Config; } diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs index f9e710a7..9518ecc8 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs @@ -137,9 +137,8 @@ public override IObservable Process(IObservable source var gpo10Config = EnableProbeSupply(serializer); // set I2C clock rate to ~400 kHz - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.SCLHIGH, 20); - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.SCLLOW, 20); - + DS90UB9x.Set933I2CRate(device, 400e3); + // read probe metadata var probeAMetadata = ReadProbeMetadata(serializer, NeuropixelsV2e.ProbeASelected); var probeBMetadata = ReadProbeMetadata(serializer, NeuropixelsV2e.ProbeBSelected); @@ -210,7 +209,7 @@ public override IObservable Process(IObservable source var deviceInfo = new NeuropixelsV2eDeviceInfo(context, DeviceType, deviceAddress, gainCorrectionA, gainCorrectionB); var shutdown = Disposable.Create(() => { - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO10, NeuropixelsV2e.DefaultGPO10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, NeuropixelsV2e.DefaultGPO10Config); SelectProbe(serializer, NeuropixelsV2e.NoProbeSelected); }); return new CompositeDisposable( @@ -237,10 +236,10 @@ static void ConfigureDeserializer(DeviceContext device) device.WriteRegister(DS90UB9x.DATALINES0, 0xFFFFF8A6); // NP A device.WriteRegister(DS90UB9x.DATALINES1, 0xFFFFF97B); // NP B + DS90UB9x.Initialize933SerDesLink(device, DS90UB9xMode.Raw12BitHighFrequency); + // configure deserializer I2C aliases var deserializer = new I2CRegisterContext(device, DS90UB9x.DES_ADDR); - uint coaxMode = 0x4 + (uint)DS90UB9xMode.Raw12BitHighFrequency; // 0x4 maintains coax mode - deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.PortMode, coaxMode); uint alias = NeuropixelsV2e.ProbeAddress << 1; deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveID1, alias); @@ -257,7 +256,7 @@ static uint EnableProbeSupply(I2CRegisterContext serializer) SelectProbe(serializer, NeuropixelsV2e.NoProbeSelected); // turn on analog supply and wait for boot - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); System.Threading.Thread.Sleep(20); return gpo10Config; } @@ -269,16 +268,16 @@ static NeuropixelsV2eMetadata ReadProbeMetadata(I2CRegisterContext serializer, b } static void SelectProbe(I2CRegisterContext serializer, byte probeSelect) { - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO32, probeSelect); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, probeSelect); System.Threading.Thread.Sleep(20); } static void ResetProbes(I2CRegisterContext serializer, uint gpo10Config) { gpo10Config &= ~NeuropixelsV2e.GPO10ResetMask; - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); gpo10Config |= NeuropixelsV2e.GPO10ResetMask; - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); } static void ConfigureProbeStreaming(I2CRegisterContext i2cNP) diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs index 40cfb0ca..23e16a5e 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs @@ -150,12 +150,11 @@ public override IObservable Process(IObservable source var serializer = new I2CRegisterContext(device, DS90UB9x.SER_ADDR); var gpo10Config = NeuropixelsV2eBeta.DefaultGPO10Config; var gpo32Config = NeuropixelsV2eBeta.DefaultGPO32Config; - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO10, gpo10Config); - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO32, gpo32Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, gpo32Config); // set I2C clock rate to ~400 kHz - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.SCLHIGH, 20); - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.SCLLOW, 20); + DS90UB9x.Set933I2CRate(device, 400e3); // read probe metadata var probeAMetadata = ReadProbeMetadata(serializer, ref gpo32Config, NeuropixelsV2eBeta.SelectProbeA); @@ -170,7 +169,7 @@ public override IObservable Process(IObservable source // REC_NRESET and NRESET go high on both probes to take the ASIC out of reset // TODO: not sure if REC_NRESET and NRESET are tied together on flex gpo10Config |= NeuropixelsV2eBeta.GPO10ResetMask | NeuropixelsV2eBeta.GPO10NResetMask; - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); System.Threading.Thread.Sleep(20); // configure probe streaming @@ -227,7 +226,7 @@ public override IObservable Process(IObservable source // toggle probe LED gpo32Config = (gpo32Config & ~NeuropixelsV2eBeta.GPO32LedMask) | (EnableLed ? 0 : NeuropixelsV2eBeta.GPO32LedMask); - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO32, gpo32Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, gpo32Config); // Both probes are now streaming, hit them with a mux reset to (roughly) sync. // NB: We have found that this gives PCLK-level synchronization MOST of the time. @@ -238,8 +237,8 @@ public override IObservable Process(IObservable source var deviceInfo = new NeuropixelsV2eDeviceInfo(context, DeviceType, deviceAddress, gainCorrectionA, gainCorrectionB); var shutdown = Disposable.Create(() => { - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO10, NeuropixelsV2eBeta.DefaultGPO10Config); - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO32, NeuropixelsV2eBeta.DefaultGPO32Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, NeuropixelsV2eBeta.DefaultGPO10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, NeuropixelsV2eBeta.DefaultGPO32Config); }); return new CompositeDisposable( DeviceManager.RegisterDevice(deviceName, deviceInfo), @@ -265,10 +264,10 @@ static void ConfigureDeserializer(DeviceContext device) device.WriteRegister(DS90UB9x.DATALINES0, 0x00007654); // NP A device.WriteRegister(DS90UB9x.DATALINES1, 0x00000123); // NP B + DS90UB9x.Initialize933SerDesLink(device, DS90UB9xMode.Raw12BitHighFrequency); + // configure deserializer I2C aliases var deserializer = new I2CRegisterContext(device, DS90UB9x.DES_ADDR); - uint coaxMode = 0x4 + (uint)DS90UB9xMode.Raw12BitHighFrequency; // 0x4 maintains coax mode - deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.PortMode, coaxMode); uint alias = NeuropixelsV2eBeta.ProbeAddress << 1; deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveID1, alias); @@ -293,17 +292,17 @@ static void SelectProbe(I2CRegisterContext serializer, ref uint gpo32Config, byt NeuropixelsV2eBeta.SelectProbeB => gpo32Config & ~NeuropixelsV2eBeta.ProbeSelectMask, _ => gpo32Config }; - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO32, gpo32Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, gpo32Config); System.Threading.Thread.Sleep(20); } static void SyncProbes(I2CRegisterContext serializer, uint gpo10Config) { gpo10Config &= ~NeuropixelsV2eBeta.GPO10NResetMask; - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); gpo10Config |= NeuropixelsV2eBeta.GPO10NResetMask; - serializer.WriteByte((uint)DS90UB9xSerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); } static void ConfigureProbeStreaming(I2CRegisterContext i2cNP) From 786d3bd0a47e4cf44dc5fab633e10620582750da Mon Sep 17 00:00:00 2001 From: Aaron Cuevas Lopez Date: Mon, 14 Oct 2024 17:18:14 +0200 Subject: [PATCH 5/7] Remove redundant and fail-prone serializer calls to set i2c rate in ConfigureDeserializer --- OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs b/OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs index ef3a82e6..5c4adddd 100644 --- a/OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs +++ b/OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs @@ -205,11 +205,6 @@ internal static void ConfigureDeserializer(DeviceContext device) i2cAlias = UclaMiniscopeV4.Max14574Address << 1; deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveID3, i2cAlias); deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SlaveAlias3, i2cAlias); - - // set I2C clock rate to ~100 kHz - var serializer = new I2CRegisterContext(device, DS90UB9x.SER_ADDR); - serializer.WriteByte((uint)0x11, 0x7A); - serializer.WriteByte((uint)0x12, 0x7A); } internal static void ConfigureSerializer(DeviceContext device) From 93bd98d05017f34bc52f6d6d0bc73bc9388e409c Mon Sep 17 00:00:00 2001 From: jonnew Date: Mon, 14 Oct 2024 12:37:42 -0400 Subject: [PATCH 6/7] Added 100 ms delay at start of Initialize933SerDesLink - Seems to help with stability --- OpenEphys.Onix1/ConfigureNeuropixelsV1e.cs | 10 ++--- OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs | 10 ++--- .../ConfigureNeuropixelsV2eBeta.cs | 18 ++++---- .../ConfigureUclaMiniscopeV4Camera.cs | 1 - OpenEphys.Onix1/DS90UB9x.cs | 42 ++++++++----------- 5 files changed, 36 insertions(+), 45 deletions(-) diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV1e.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV1e.cs index 39541a95..8ab8d9ea 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV1e.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV1e.cs @@ -166,8 +166,8 @@ public override IObservable Process(IObservable source var deviceInfo = new NeuropixelsV1eDeviceInfo(context, DeviceType, deviceAddress, probeControl); var shutdown = Disposable.Create(() => { - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, NeuropixelsV1e.DefaultGPO10Config); - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, NeuropixelsV1e.DefaultGPO32Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio10, NeuropixelsV1e.DefaultGPO10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio32, NeuropixelsV1e.DefaultGPO32Config); }); return new CompositeDisposable( DeviceManager.RegisterDevice(deviceName, deviceInfo), @@ -210,16 +210,16 @@ static void ConfigureDeserializer(DeviceContext device) static void ResetProbe(I2CRegisterContext serializer, uint gpo10Config) { gpo10Config &= ~NeuropixelsV1e.Gpo10ResetMask; - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio10, gpo10Config); Thread.Sleep(1); gpo10Config |= NeuropixelsV1e.Gpo10ResetMask; - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio10, gpo10Config); } static uint TurnOnLed(I2CRegisterContext serializer, uint gpo23Config) { gpo23Config &= ~NeuropixelsV1e.Gpo32LedMask; - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, gpo23Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio32, gpo23Config); return gpo23Config; } diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs index 9518ecc8..4336dcc4 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs @@ -209,7 +209,7 @@ public override IObservable Process(IObservable source var deviceInfo = new NeuropixelsV2eDeviceInfo(context, DeviceType, deviceAddress, gainCorrectionA, gainCorrectionB); var shutdown = Disposable.Create(() => { - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, NeuropixelsV2e.DefaultGPO10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio10, NeuropixelsV2e.DefaultGPO10Config); SelectProbe(serializer, NeuropixelsV2e.NoProbeSelected); }); return new CompositeDisposable( @@ -256,7 +256,7 @@ static uint EnableProbeSupply(I2CRegisterContext serializer) SelectProbe(serializer, NeuropixelsV2e.NoProbeSelected); // turn on analog supply and wait for boot - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio10, gpo10Config); System.Threading.Thread.Sleep(20); return gpo10Config; } @@ -268,16 +268,16 @@ static NeuropixelsV2eMetadata ReadProbeMetadata(I2CRegisterContext serializer, b } static void SelectProbe(I2CRegisterContext serializer, byte probeSelect) { - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, probeSelect); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio32, probeSelect); System.Threading.Thread.Sleep(20); } static void ResetProbes(I2CRegisterContext serializer, uint gpo10Config) { gpo10Config &= ~NeuropixelsV2e.GPO10ResetMask; - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio10, gpo10Config); gpo10Config |= NeuropixelsV2e.GPO10ResetMask; - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio10, gpo10Config); } static void ConfigureProbeStreaming(I2CRegisterContext i2cNP) diff --git a/OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs b/OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs index 23e16a5e..1e317e4e 100644 --- a/OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs +++ b/OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs @@ -150,8 +150,8 @@ public override IObservable Process(IObservable source var serializer = new I2CRegisterContext(device, DS90UB9x.SER_ADDR); var gpo10Config = NeuropixelsV2eBeta.DefaultGPO10Config; var gpo32Config = NeuropixelsV2eBeta.DefaultGPO32Config; - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, gpo32Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio32, gpo32Config); // set I2C clock rate to ~400 kHz DS90UB9x.Set933I2CRate(device, 400e3); @@ -169,7 +169,7 @@ public override IObservable Process(IObservable source // REC_NRESET and NRESET go high on both probes to take the ASIC out of reset // TODO: not sure if REC_NRESET and NRESET are tied together on flex gpo10Config |= NeuropixelsV2eBeta.GPO10ResetMask | NeuropixelsV2eBeta.GPO10NResetMask; - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio10, gpo10Config); System.Threading.Thread.Sleep(20); // configure probe streaming @@ -226,7 +226,7 @@ public override IObservable Process(IObservable source // toggle probe LED gpo32Config = (gpo32Config & ~NeuropixelsV2eBeta.GPO32LedMask) | (EnableLed ? 0 : NeuropixelsV2eBeta.GPO32LedMask); - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, gpo32Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio32, gpo32Config); // Both probes are now streaming, hit them with a mux reset to (roughly) sync. // NB: We have found that this gives PCLK-level synchronization MOST of the time. @@ -237,8 +237,8 @@ public override IObservable Process(IObservable source var deviceInfo = new NeuropixelsV2eDeviceInfo(context, DeviceType, deviceAddress, gainCorrectionA, gainCorrectionB); var shutdown = Disposable.Create(() => { - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, NeuropixelsV2eBeta.DefaultGPO10Config); - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, NeuropixelsV2eBeta.DefaultGPO32Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio10, NeuropixelsV2eBeta.DefaultGPO10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio32, NeuropixelsV2eBeta.DefaultGPO32Config); }); return new CompositeDisposable( DeviceManager.RegisterDevice(deviceName, deviceInfo), @@ -292,17 +292,17 @@ static void SelectProbe(I2CRegisterContext serializer, ref uint gpo32Config, byt NeuropixelsV2eBeta.SelectProbeB => gpo32Config & ~NeuropixelsV2eBeta.ProbeSelectMask, _ => gpo32Config }; - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO32, gpo32Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio32, gpo32Config); System.Threading.Thread.Sleep(20); } static void SyncProbes(I2CRegisterContext serializer, uint gpo10Config) { gpo10Config &= ~NeuropixelsV2eBeta.GPO10NResetMask; - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio10, gpo10Config); gpo10Config |= NeuropixelsV2eBeta.GPO10NResetMask; - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.GPIO10, gpo10Config); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.Gpio10, gpo10Config); } static void ConfigureProbeStreaming(I2CRegisterContext i2cNP) diff --git a/OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs b/OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs index 5c4adddd..8911167c 100644 --- a/OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs +++ b/OpenEphys.Onix1/ConfigureUclaMiniscopeV4Camera.cs @@ -3,7 +3,6 @@ using System.Drawing.Design; using System.Reactive.Disposables; using System.Reactive.Subjects; -using System.Threading; using System.Xml.Serialization; using Bonsai; diff --git a/OpenEphys.Onix1/DS90UB9x.cs b/OpenEphys.Onix1/DS90UB9x.cs index 48e56b1e..8a6a489e 100644 --- a/OpenEphys.Onix1/DS90UB9x.cs +++ b/OpenEphys.Onix1/DS90UB9x.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; namespace OpenEphys.Onix1 { @@ -34,12 +35,14 @@ static class DS90UB9x internal static void Initialize933SerDesLink(DeviceContext device, DS90UB9xMode dataMode) //also valid for 913 { + Thread.Sleep(100); // Empirical. The gateware seems to need some milliseconds to get i2c initialized. + var deserializer = new I2CRegisterContext(device, DES_ADDR); - deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.PortSel, 0x01); //Enable port 0 - deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.PortMode, 0x4 + (uint)dataMode); //0x4 maintains coax mode - deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.I2CConfig, 0b01011000); //7: i2c pass all (0), 6: i2c pass (1), 5: auto_ack (0), 4: BC enable (1), 3: BC crc en (1), 2: reserved (0) 1:0: bc freq (00) 2.5Mbps + deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.PortSel, 0x01); // Enable port 0 + deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.PortMode, 0x4 + (uint)dataMode); // 0x4 maintains coax mode + deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.I2CConfig, 0b01011000); // 7: i2c pass all (0), 6: i2c pass (1), 5: auto_ack (0), 4: BC enable (1), 3: BC crc en (1), 2: reserved (0) 1:0: bc freq (00) 2.5Mbps deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.SerAlias, SER_ADDR << 1); - //Enable backchannel GPIO on deserializer. It is then the serializer task to decide if using them or use manual output + // Enable backchannel GPIO on deserializer. It is then the serializer task to decide if using them or use manual output deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.GpioCtrl0, 0x10); deserializer.WriteByte((uint)DS90UB9xDeserializerI2CRegister.GpioCtrl0, 0x32); } @@ -49,10 +52,9 @@ internal static void Set933I2CRate(DeviceContext device, double i2cRate) var serializer = new I2CRegisterContext(device, SER_ADDR); double SCLtimes = (1.0 / (100e-9 * i2cRate)); uint SCLvalir = (uint)Math.Round(SCLtimes); - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.SCLHIGH, SCLvalir); - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.SCLLOW, SCLvalir); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.SclHigh, SCLvalir); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.SclLow, SCLvalir); } - } enum DS90UB9xTriggerMode : uint @@ -113,28 +115,20 @@ enum DS90UB9xDeserializerI2CRegister SlaveAlias7 = 0x6C, } -// enum DS90UB9xSerializerI2CRegister -// { -// GPIO10 = 0x0D, -// GPIO32 = 0x0E, -// SCLHIGH = 0x0A, -// SCLLOW = 0x0B -// } - enum DS90UB933SerializerI2CRegister { - GPIO10 = 0x0D, - GPIO32 = 0x0E, - SCLHIGH = 0x11, - SCLLOW = 0x12 + Gpio10 = 0x0D, + Gpio32 = 0x0E, + SclHigh = 0x11, + SclLow = 0x12 } enum DS90UB953SerializerI2CRegister { - GPIO_DATA = 0x0D, - GPIO_IO_CTRL = 0x0E, - SCLHIGH = 0x0B, - SCLLOW = 0x0C + GpioData = 0x0D, + GpioIOControl = 0x0E, + SclHigh = 0x0B, + SclLow = 0x0C } enum DS90UB9xMode @@ -149,6 +143,4 @@ enum DS90UB9xDirection Input = 0, Output = 1 } - - } From a9e386f89070ed2d0a31138a64ddea2081467b48 Mon Sep 17 00:00:00 2001 From: jonnew Date: Tue, 15 Oct 2024 15:50:08 -0400 Subject: [PATCH 7/7] - Minor variable name changes --- OpenEphys.Onix1/DS90UB9x.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/OpenEphys.Onix1/DS90UB9x.cs b/OpenEphys.Onix1/DS90UB9x.cs index 8a6a489e..4d92cbd1 100644 --- a/OpenEphys.Onix1/DS90UB9x.cs +++ b/OpenEphys.Onix1/DS90UB9x.cs @@ -50,10 +50,9 @@ static class DS90UB9x internal static void Set933I2CRate(DeviceContext device, double i2cRate) { var serializer = new I2CRegisterContext(device, SER_ADDR); - double SCLtimes = (1.0 / (100e-9 * i2cRate)); - uint SCLvalir = (uint)Math.Round(SCLtimes); - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.SclHigh, SCLvalir); - serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.SclLow, SCLvalir); + var sclTimes = (uint)Math.Round(1.0 / (100e-9 * i2cRate)); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.SclHigh, sclTimes); + serializer.WriteByte((uint)DS90UB933SerializerI2CRegister.SclLow, sclTimes); } }