Exemplo n.º 1
0
        public void WriteConfiguration(NeuropixelsConfiguration config, bool read_check = false)
        {
            if (config.Channels.Length != CHANNEL_COUNT)
            {
                throw new ArgumentException("Incorrect number of channels for this probe.", "config");
            }

            if (config.ADCs.Length != ADC_COUNT)
            {
                throw new ArgumentException("Incorrect number of ADCs for this probe.", "config");
            }

            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.", "config");
            }

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

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

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

                case NeuropixelsConfiguration.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, ShankConfig(config), false);

            // NB: NP API uploads ADC gain correction at this point, but we are using a downstream transform to do this.
            // This process does not mutate base_config bit arrays

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

            WriteShiftRegister((uint)RegAddr.SR_CHAIN2, base_configs[0], read_check);
            WriteShiftRegister((uint)RegAddr.SR_CHAIN3, base_configs[1], read_check);
        }
Exemplo n.º 2
0
        // Convert Channels into BitArray
        BitArray ShankConfig(NeuropixelsConfiguration config)
        {
            // Default
            var shank_config = new BitArray(SHANK_CONFIG_BITS, false);

            // If external reference is used by any channel
            var b = config.Channels.Where(ch => ch.Reference == Channel.Ref.EXTERNAL).Count() > 0;

            shank_config[SHANK_BIT_EXT1] = b;
            shank_config[SHANK_BIT_EXT2] = b;

            // If tip reference is used by any channel
            b = config.Channels.Where(ch => ch.Reference == Channel.Ref.TIP).Count() > 0;
            shank_config[SHANK_BIT_TIP1] = b;
            shank_config[SHANK_BIT_TIP2] = b;

            // 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;

            b = config.Channels.Where(ch => ch.Reference == Channel.Ref.INTERNAL).Count() > 0;
            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.GetElectrode(i);
                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);
        }
Exemplo n.º 3
0
        public NeuropixelsV1Device() : base(ONIXDevices.ID.NEUROPIX1R0)
        {
            Configuration            = new NeuropixelsConfiguration();
            Configuration.Channels   = new NeuropixelsChannel[NeuropixelsV1Probe.CHANNEL_COUNT];
            Configuration.ADCs       = new NeuropixelsADC[NeuropixelsV1Probe.ADC_COUNT];
            Configuration.Electrodes = new NeuropixelsElectrode[NeuropixelsV1Probe.ELECTRODE_COUNT];

            for (int i = 0; i < Configuration.Channels.Length; i++)
            {
                Configuration.Channels[i] = new NeuropixelsChannel();
            }

            Configuration.InternalReferenceChannels = new int[] { NeuropixelsV1Probe.INTERNAL_REF_CHANNEL };

            for (int i = 0; i < Configuration.ADCs.Length; i++)
            {
                Configuration.ADCs[i] = new NeuropixelsADC();
            }

            for (int i = 0; i < Configuration.Electrodes.Length; i++)
            {
                Configuration.Electrodes[i] = new NeuropixelsElectrode();
            }
        }
Exemplo n.º 4
0
        // Convert Channels & ADCs into BitArray
        BitArray[] BaseConfig(NeuropixelsConfiguration 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;
            }

            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);
        }