Ejemplo n.º 1
0
 private void WriteADCCorrections(NeuropixelsV1Configuration config)
 {
     for (int i = 0; i < config.ADCs.Length; i += 2)
     {
         var addr = (uint)Register.ADC01_00_OFF_THRESH + (uint)i / 2;
         var adc0 = (uint)config.ADCs[i].Offset << 10 | (uint)config.ADCs[i].Threshold;
         var adc1 = (uint)config.ADCs[i + 1].Offset << 10 | (uint)config.ADCs[i].Threshold;
         var val  = adc1 << 16 | adc0;
         WriteManagedRegister(addr, val);
     }
 }
Ejemplo n.º 2
0
 private void WriteAPGainCorrections(NeuropixelsV1Configuration config)
 {
     for (int i = 0; i < config.Channels.Length; i += 2)
     {
         var addr        = (uint)Register.CHAN001_000_APGAIN + (uint)i / 2;
         var gain_fixed0 = (uint)(config.Channels[i].APGainCorrection * (1 << 14));
         var gain_fixed1 = (uint)(config.Channels[i + 1].APGainCorrection * (1 << 14));
         var val         = gain_fixed1 << 16 | gain_fixed0;
         WriteManagedRegister(addr, val);
     }
 }
Ejemplo n.º 3
0
        public void WriteConfiguration(NeuropixelsV1Configuration config, bool performReadCheck = false)
        {
            if (config.Channels.ToList().GetRange(192, 192).Any(c => c.Bank == Channel.ElectrodeBank.TWO))
            {
                throw new ArgumentException("Electrode selection is out of bounds. Only bank 0 and 1 are valid for channels in range 192..383.", nameof(config));
            }

            // Turn on calibration if necessary
            if (config.Mode != NeuropixelsV1Configuration.OperationMode.RECORD)
            {
                switch (config.Mode)
                {
                case NeuropixelsV1Configuration.OperationMode.CALIBRATE_ADCS:
                    WriteByte((uint)RegAddr.CAL_MOD, (uint)CalMod.OSC_ACTIVE_AND_ADC_CAL);
                    WriteByte((uint)RegAddr.OP_MODE, (uint)Operation.RECORD_AND_CALIBRATE);
                    break;

                case NeuropixelsV1Configuration.OperationMode.CALIBRATE_CHANNELS:
                    WriteByte((uint)RegAddr.CAL_MOD, (uint)CalMod.OSC_ACTIVE_AND_CH_CAL);
                    WriteByte((uint)RegAddr.OP_MODE, (uint)Operation.RECORD_AND_CALIBRATE);
                    break;

                case NeuropixelsV1Configuration.OperationMode.CALIBRATE_PIXELS:
                    WriteByte((uint)RegAddr.CAL_MOD, (uint)CalMod.OSC_ACTIVE_AND_PIX_CAL);
                    WriteByte((uint)RegAddr.OP_MODE, (uint)Operation.RECORD_AND_CALIBRATE);
                    break;

                case NeuropixelsV1Configuration.OperationMode.DIGITAL_TEST:
                    WriteByte((uint)RegAddr.OP_MODE, (uint)Operation.RECORD_AND_DIG_TEST);
                    break;
                }
            }

            // Shank configuration
            // NB: ASIC bug, read_check on SR_CHAIN1 ignored
            WriteShiftRegister((uint)RegAddr.SR_CHAIN1, GenerateShankBits(config), false);

            // Gain and ADC corrections
            WriteLFPGainCorrections(config);
            WriteAPGainCorrections(config);
            WriteADCCorrections(config);
            ConfigProbeSN = config.ConfigProbeSN;

            // Base configurations
            var base_configs = GenerateBaseBits(config);

            WriteShiftRegister((uint)RegAddr.SR_CHAIN2, base_configs[0], performReadCheck);
            WriteShiftRegister((uint)RegAddr.SR_CHAIN3, base_configs[1], performReadCheck);

            // Configuration has been uploaded
            config.RefreshNeeded = false;
        }
Ejemplo n.º 4
0
        // Convert Channels into BitArray
        private static BitArray GenerateShankBits(NeuropixelsV1Configuration config)
        {
            // Default
            var shank_config = new BitArray(SHANK_CONFIG_BITS, false);

            // If external reference is used by any channel
            shank_config[SHANK_BIT_EXT1] = config.Channels.Where(ch => ch.Reference == Channel.Ref.EXTERNAL && ch.ElectrodeNumber % 2 == 1).Any();
            shank_config[SHANK_BIT_EXT2] = config.Channels.Where(ch => ch.Reference == Channel.Ref.EXTERNAL && ch.ElectrodeNumber % 2 == 0).Any();

            // If tip reference is used by any channel
            shank_config[SHANK_BIT_TIP1] = config.Channels.Where(ch => ch.Reference == Channel.Ref.TIP && ch.ElectrodeNumber % 2 == 1).Any();
            shank_config[SHANK_BIT_TIP2] = config.Channels.Where(ch => ch.Reference == Channel.Ref.TIP && ch.ElectrodeNumber % 2 == 0).Any();

            // If internal reference is used by any channel
            var refs = BankToIntRef.Values.ToArray();

            shank_config[refs[0]] = false;
            shank_config[refs[1]] = false;
            shank_config[refs[2]] = false;

            var b = config.Channels.Where(ch => ch.Reference == Channel.Ref.INTERNAL).Any();

            shank_config[refs[(int)config.Channels[INTERNAL_REF_CHANNEL].Bank]] = b;

            // Update active channels
            for (int i = 0; i < config.Channels.Length; i++)
            {
                // Reference bits always remain zero
                if (i == INTERNAL_REF_CHANNEL)
                {
                    continue;
                }

                var e = config.Channels[i].ElectrodeNumber;
                if (e != null)
                {
                    int bit_idx = e % 2 == 0 ?
                                  485 + ((int)e / 2) : // even electrode
                                  482 - ((int)e / 2);  // odd electrode
                    shank_config[bit_idx] = true;
                }
            }

            return(shank_config);
        }
Ejemplo n.º 5
0
        // Convert Channels & ADCs into BitArray
        private static BitArray[] GenerateBaseBits(NeuropixelsV1Configuration config)
        {
            // MSB [Full, standby, LFPGain(3 downto 0), APGain(3 downto0)] LSB
            BitArray[] base_configs = { new BitArray(BASE_CONFIG_BITS, false),   // Ch 0, 2, 4, ...
                                        new BitArray(BASE_CONFIG_BITS, false) }; // Ch 1, 3, 5, ...

            // Channels section
            for (int i = 0; i < config.Channels.Length; i++)
            {
                var config_idx = i % 2;

                // References
                var ref_idx = config_idx == 0 ?
                              (382 - i) / 2 * 3 :
                              (383 - i) / 2 * 3;

                base_configs[config_idx][ref_idx + (int)config.Channels[i].Reference] = true;

                // Gains, standby, and filter
                var ch_opts_idx = PROBE_SRBASECONFIG_BIT_GAINBASE + ((i - config_idx) * 4);

                base_configs[config_idx][ch_opts_idx + 0] = Gains[config.Channels[i].APGain][0];
                base_configs[config_idx][ch_opts_idx + 1] = Gains[config.Channels[i].APGain][1];
                base_configs[config_idx][ch_opts_idx + 2] = Gains[config.Channels[i].APGain][2];

                base_configs[config_idx][ch_opts_idx + 3] = Gains[config.Channels[i].LFPGain][0];
                base_configs[config_idx][ch_opts_idx + 4] = Gains[config.Channels[i].LFPGain][1];
                base_configs[config_idx][ch_opts_idx + 5] = Gains[config.Channels[i].LFPGain][2];

                base_configs[config_idx][ch_opts_idx + 6] = config.Channels[i].Standby;
                base_configs[config_idx][ch_opts_idx + 7] = config.Channels[i].APFilter; // Correct?
            }

            int k = 0;

            foreach (var adc in config.ADCs)
            {
                if (adc.CompP < 0 || adc.CompP > 0x1F)
                {
                    throw new ArgumentOutOfRangeException(String.Format("ADC calibration parameter CompP value of {0} is invalid.", adc.CompP));
                }

                if (adc.CompN < 0 || adc.CompN > 0x1F)
                {
                    throw new ArgumentOutOfRangeException(String.Format("ADC calibration parameter CompN value of {0} is invalid.", adc.CompN));
                }

                if (adc.Cfix < 0 || adc.Cfix > 0xF)
                {
                    throw new ArgumentOutOfRangeException(String.Format("ADC calibration parameter Cfix value of {0} is invalid.", adc.Cfix));
                }

                if (adc.Slope < 0 || adc.Slope > 0x7)
                {
                    throw new ArgumentOutOfRangeException(String.Format("ADC calibration parameter Slope value of {0} is invalid.", adc.Slope));
                }

                if (adc.Coarse < 0 || adc.Coarse > 0x3)
                {
                    throw new ArgumentOutOfRangeException(String.Format("ADC calibration parameter Coarse value of {0} is invalid.", adc.Coarse));
                }

                if (adc.Fine < 0 || adc.Fine > 0x3)
                {
                    throw new ArgumentOutOfRangeException(String.Format("ADC calibration parameter Fine value of {0} is invalid.", adc.Fine));
                }

                var config_idx = k % 2;
                int d          = k++ / 2;

                int comp_off  = 2406 - 42 * (d / 2) + (d % 2) * 10;
                int slope_off = comp_off + 20 + (d % 2);

                BitArray comp_p = new BitArray(new byte[] { (byte)adc.CompP });
                BitArray comp_n = new BitArray(new byte[] { (byte)adc.CompN });
                BitArray cfix   = new BitArray(new byte[] { (byte)adc.Cfix });
                BitArray slope  = new BitArray(new byte[] { (byte)adc.Slope });
                BitArray coarse = (new BitArray(new byte[] { (byte)adc.Coarse }));
                BitArray fine   = new BitArray(new byte[] { (byte)adc.Fine });

                base_configs[config_idx][comp_off + 0] = comp_p[0];
                base_configs[config_idx][comp_off + 1] = comp_p[1];
                base_configs[config_idx][comp_off + 2] = comp_p[2];
                base_configs[config_idx][comp_off + 3] = comp_p[3];
                base_configs[config_idx][comp_off + 4] = comp_p[4];

                base_configs[config_idx][comp_off + 5] = comp_n[0];
                base_configs[config_idx][comp_off + 6] = comp_n[1];
                base_configs[config_idx][comp_off + 7] = comp_n[2];
                base_configs[config_idx][comp_off + 8] = comp_n[3];
                base_configs[config_idx][comp_off + 9] = comp_n[4];

                base_configs[config_idx][slope_off + 0] = slope[0];
                base_configs[config_idx][slope_off + 1] = slope[1];
                base_configs[config_idx][slope_off + 2] = slope[2];

                base_configs[config_idx][slope_off + 3] = fine[0];
                base_configs[config_idx][slope_off + 4] = fine[1];

                base_configs[config_idx][slope_off + 5] = coarse[0];
                base_configs[config_idx][slope_off + 6] = coarse[1];

                base_configs[config_idx][slope_off + 7]  = cfix[0];
                base_configs[config_idx][slope_off + 8]  = cfix[1];
                base_configs[config_idx][slope_off + 9]  = cfix[2];
                base_configs[config_idx][slope_off + 10] = cfix[3];
            }

            return(base_configs);
        }