Skip to content

Commit

Permalink
Update I2C accesses on Neuropixel devices
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
aacuevas committed Oct 13, 2024
1 parent d9832ac commit fcf84e7
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 32 deletions.
17 changes: 8 additions & 9 deletions OpenEphys.Onix1/ConfigureNeuropixelsV1e.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,7 @@ public override IObservable<ContextTask> Process(IObservable<ContextTask> 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);
Expand All @@ -167,8 +166,8 @@ public override IObservable<ContextTask> Process(IObservable<ContextTask> 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),
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down
19 changes: 9 additions & 10 deletions OpenEphys.Onix1/ConfigureNeuropixelsV2e.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,8 @@ public override IObservable<ContextTask> Process(IObservable<ContextTask> 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);
Expand Down Expand Up @@ -210,7 +209,7 @@ public override IObservable<ContextTask> Process(IObservable<ContextTask> 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(
Expand All @@ -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);
Expand All @@ -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;
}
Expand All @@ -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)
Expand Down
25 changes: 12 additions & 13 deletions OpenEphys.Onix1/ConfigureNeuropixelsV2eBeta.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,11 @@ public override IObservable<ContextTask> Process(IObservable<ContextTask> 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);
Expand All @@ -170,7 +169,7 @@ public override IObservable<ContextTask> Process(IObservable<ContextTask> 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
Expand Down Expand Up @@ -227,7 +226,7 @@ public override IObservable<ContextTask> Process(IObservable<ContextTask> 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.
Expand All @@ -238,8 +237,8 @@ public override IObservable<ContextTask> Process(IObservable<ContextTask> 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),
Expand All @@ -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);
Expand All @@ -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)
Expand Down

0 comments on commit fcf84e7

Please sign in to comment.