## Overview

Neurosdk is a powerful tool for working with neuro-sensors BrainBit, BrainBitBlack, NeuroEEG-M, Callibri and Kolibri. All these devices work with BLE 4.0+ technology. SDK allows you to connect, read the parameters of devices, as well as receive signals of various types from the selected device. 

## Getting Started

Firstly, you need to install package. 

### ReactNative

> Available for iOS and Android platforms

## Installation

### By npm:

`$ npm install react-native-neurosdk2 --save`

### Mostly automatic installation:

`$ react-native link react-native-neurosdk2`

### After installation

Because sdk uses the bluetooth api you need to set up the project. 

For Android you need to request runtime permission:

```ts
async function requestPermissionAndroid() {
  try {
    let permissions: Array<Permission> = [];

    let androidApi31 = Platform.constants['Release'] >= 31;

    if (androidApi31) { // for android 12 (api 31+)
      permissions.push(PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN);
      permissions.push(PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT);
    } else {
      permissions.push(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION);
      permissions.push(PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION);
    }

    if (permissions.length == 0) { return; }

    const result = await PermissionsAndroid.requestMultiple(permissions);

    for (let i = 0; i < permissions.length; i++) {
      const perm = permissions[i];
      if (perm !== undefined && result[perm] != PermissionsAndroid.RESULTS.GRANTED) {
        requestPermissionAndroid();
      }
    }
  } catch (err) {
    console.warn(err);
  }
}
```

For iOS you need to add a key to `Info.plist` because it uses bluetooth too:

```
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Explanation to using bluetooth</string>
```

## Usage

SDK can be conditionally divided into two parts: device search (Scanner object) and the device itself (Sensor object).

The scanner allows you to find devices nearby, it is also responsible for the first creation of the device. When created, the device is automatically connected. In the future, the connection state can be controlled through the sensor object. Whatever type of device you work with, the use of the scanner will be the same.

The sensor allows you to monitor the status of the device, set parameters, receive a signal of various types. 

>It is recommended to work with both parts in a separate thread. During the connection, the SDK also reads the main characteristics of the device, which significantly increases the time of the connection method, which will cause the application to freeze.

If an error occurs while working with the library, you will receive an exception for any of the methods.

### Description

Package contains tree main modules:

 - Scanner - to search for devices

```js
import { Scanner } from 'react-native-neurosdk2'
```

 - Sensor - methods of interaction with the device

 ```js
 import { Sensor, BrainBitSensor, BrainBit2Sensor, BrainBitBlackSensor, CallibriSensor, NeuroEEGSensor } from 'react-native-neurosdk2'
 ```

 - Types - implementation of all types of the library, you can either connect everything or only those necessary for a specific task

 ```js
 import {SensorSamplingFrequency, 
    SensorGain,
    SensorDataOffset,
    SensorExternalSwitchInput,
    SensorADCInput,
    SensorAccelerometerSensitivity,
    SensorGyroscopeSensitivity,
    SensorFirmwareMode,
    IrAmplitude,
    RedAmplitude,
    FPGData,
    SensorAmpMode,
    SensorCommand,
    SensorParamAccess,
    SensorParameter,
    SensorFeature,
    SensorFilter,
    SensorFamily,
    SensorInfo,
    SensorVersion,
    MEMSData,
    Point3D,
    BrainBitSignalData,
    BrainBitResistData,
    CallibriSignalData,
    CallibriEnvelopeData,
    CallibriRespirationData,
    CallibriColorType,
    CallibriSignalType,
    CallibriStimulatorMAState,
    CallibriStimulationParams,
    CallibriMotionAssistantParams,
    CallibriMotionCounterParam,
    QuaternionData,
    CallibriElectrodeState,
    CallibriMotionAssistantLimb,
    CallibriStimulatorState,
    SignalChannelsData,
    ResistChannelsData,
    EEGChannelInfo,
    EEGChannelId,
    EEGChannelType,
    NeuroEEGAmplifierParam,
    EEGRefMode,
    EEGChannelMode,
    GenCurrent, 
    BrainBit2AmplifierParam,
    BrainBit2ChannelMode,
    ResistRefChannelsData,
    SensorState} from 'react-native-neurosdk2'
 ```

### Errors

Here is a list of exceptions that occur when working with SDK. You need to be guided by this list in order to understand what happened in the process of executing a particular method.

| Code| Description                                             |
| ----| --------------------------------------------------------|
| 100 | Invalid scan parameters are specified                   |
| 101 | Invalid sensor types are specified for the search       |
| 102 |Failed to create sensor scanner                          |
| 103 |Failed to started sensor scanner                         |
| 104 |Failed to stopped sensor scanner                         |
| 105 |Failed to get a list of sensors                          |
| 106 |Failed to get a list of sensors                          |
| 107 |Invalid parameters for creating a sensor                 |
| 108 |Failed to create sensor                                  |
| 109 |Sensor not founded                                       |
| 110 |Failed to connect the sensor                             |
| 111 |Failed to disconnect the sensor                          |
| 112 |Failed to get a list of sensor features                  |
| 113 |Invalid parameters for get a list features of the sensor |
| 114 |Invalid parameters for get a list commands of the sensor |
| 115 |Failed to get a list of sensor commands                  |
| 116 |Invalid parameters for get a list parameters of the sensor|
| 117 |Failed to get a list of sensor parameters                |
| 118 |Failed to execute the sensor command                     |
| 119 |Failed read the sensor parameter                         |
| 120 |Failed read the sensor parameter                         |
| 121 |Failed write the sensor parameter                        |
| 122 |Failed write the sensor parameter                        |
| 123 |Failed add callback the sensor                           |
| 124 |Failed add callback the sensor                           |

### Scanner

The scanner works like this:

1. Create scanner. 
When creating a scanner, you need to specify the type of device to search. It can be either one device or several.

```ts
import {Scanner} from 'react-native-neurosdk2'

...

var scanner = new Scanner()
await scanner.init([SensorFamily.LECallibri, 
                    SensorFamily.LEBrainBit, 
                    SensorFamily.LEBrainBit2, 
                    SensorFamily.LEBrainBitFlex, 
                    SensorFamily.LEBrainBitPro, 
                    SensorFamily.LEBrainBitBlack, 
                    SensorFamily.LENeuroEEG])
```

2. During the search, you can get a list of found devices using a callback. To do this, you need to subscribe to receive the event, and unsubscribe after the search is completed:

```ts
scanner.AddSensorListChanged(sensors => {
	console.log(sensors)
});
...
scanner.RemoveSensorListChanged();
```

3. Start search

```ts
scanner.start()
```

3. Stop search

```ts
scanner.stop()
```

4. Additionally, a list of found devices can be obtained using a separate method.

```ts
var sensors = await scanner.sensors()
```

`SensorInfo` contains information about device:
 - Name - the name of device
 - Address - MAC address of device (UUID for iOS/MacOS)
 - Serial number - device's serial number
 - Sensor family - type of device
 - Sensor model - numerical value of the device model
 - Pairing requared - whether the device needs to be paired or not
 - RSSI - current signal strength in dBm. The valid range is [-127, 126]

5. After you finish working with the scanner, you need to clean up the resources used. 

```ts
scanner.close();
```

> When a found device is disconnected or loses signal, it will not immediately disappear in the scanner.


### Sensor

#### Creating

You need to create a device using a scanner. All manipulations with the device will be performed without errors only if the device is connected.

```ts
import { CallibriSensor, BrainBitSensor, NeuroEEGSensor, Sensor  } from "react-native-neurosdk2";

// BrainBit
var sensor: BrainBitSensor = await scanner.createSensor(sensorInfo) as BrainBitSensor;

// BrainBit
var sensor: BrainBitBlackSensor = await scanner.createSensor(sensorInfo) as BrainBitBlackSensor;

// BrainBit 2/Flex/Pro
var sensor: BrainBit2Sensor = await scanner.createSensor(sensorInfo) as BrainBit2Sensor;

// Callibri
var sensor: CallibriSensor = await scanner.createSensor(deviceInfo) as CallibriSensor

// NeuroEEG
var sensor: NeuroEEGSensor = await scanner.createSensor(deviceInfo) as NeuroEEGSensor
```

> For all types of devices, you can use the same methods to control the device's connection status, invoke commands, and check for functionality.

#### Manage connection state

Connection status can be obtained in two ways. The first one is using the sensor property `State`.

The second way is in real time using a callback:

```ts
sensor.AddConnectionChanged((state)=>{           
    console.log(SensorState[state])
})
...
sensor.RemoveConnectionChanged()
```

A connection can be in two states: connected (InRange) and disconnected (OutOfRange).

> Important!
> The state change callback will not come after the device is created, only after disconnecting (device lost from the scope or using a method) and then connected. The device does not automatically reconnect.

You can connect and disconnect from device manually by methods `Connect()` and `Disconnect()`. To receive connection state in real time you need to subscribe to `stateChanged` event. Also you can get connection state by sensor's property.

```ts
await sensor.disconnect()
...
await sensor.connect()
```

#### Manage device parameters

##### Battery

Also, you can get power value from each device by sensor property `BattPower` or by callback in real time:

```ts
sensor.AddBatteryChanged((power)=>{
    console.log(power)
})
...
sensor.RemoveBatteryChanged()
```

##### Parameters

Each device has its own settings, and some of them can be configured as you need. Not all settings can be changed and not every device supports all settings.

First you need to find out what parameters the device supports and whether they can be changed:

```ts
console.log(sensor.getParameters().map(parameter => SensorParameter[parameter.Param] + ": " + SensorParamAccess[parameter.ParamAccess]))

// Output:
//
// ["Name: Read", 
// "FirmwareMode: Read", 
// "FirmwareVersion: Read", 
// "State: ReadNotify", ... ]
```

Info about parameter includes two fields:
 - the name of the parameter, represented by an enumeration
 - parameter availability for manipulation. Can be one of three values:
   - read - read-only
   - read and write - parameter can be changed
   - read and notify - parameter is updated over time

You can also check if the parameter is supported, for example `Gain`:

```ts
if(sensor.isSupportedParameter(SensorParameter.Gain)){
    ...
}
```

##### Parameter description

###### Name

Name of device. String value.

```ts
var name: string = sensor.getName()
...
sensor.setName('new_name') // <- this is throw an exeption, you cannot set device name
```

###### State

Information about the connection status of a device. Can take two values:

- InRange - Device connected
- OutOfRange - The device is turned off or out of range

```ts
var state: SensorState = sensor.getState()
```

###### Address

MAC-address of device. For iOS/MacOS represents by UUID. String value.

```ts
var address: string = sensor.getAddress()
```

###### Serial number

Serial number of device.  String value.

For callibri device families, this field is empty in `SensorInfo` when searching, and you can get it immediately after connecting using this property.

```ts
var sn: string = sensor.getSerialNumber()
```

###### Channel count

Count of channels of device. Number value.

```ts
var chCount: number = sensor.getChannelsCount()()
```

###### Hardware filters

> Only to Callibri MF sensor!

Device signal filter activity states. If the parameter is supported by the device, it becomes possible to set the desired filters to the device. The next filters are available:

- HPFBwhLvl1CutoffFreq1Hz
- HPFBwhLvl1CutoffFreq5Hz
- BSFBwhLvl2CutoffFreq45_55Hz
- BSFBwhLvl2CutoffFreq55_65Hz
- HPFBwhLvl2CutoffFreq10Hz
- LPFBwhLvl2CutoffFreq400Hz
- FilterHPFBwhLvl2CutoffFreq80Hz
- FilterUnknown

> If sensor does not support filter in input list the method throw an exception

> NOTE:
> Setting a hardware filter list that contains LPFBwhLvl2CutoffFreq400Hz will not occur in a callibri sensor at a frequency other than 1000Hz

```ts
var filters: Array<SensorFilter> = sensor.getHardwareFilters()
...
sensor.setHardwareFilters([SensorFilter.FilterBSFBwhLvl2CutoffFreq55_65Hz, SensorFilter.FilterHPFBwhLvl2CutoffFreq10Hz])
```

You can also check if the filter is supported, for example `HPFBwhLvl1CutoffFreq1Hz`:

```ts
if(sensor.isSupportedFilter(SensorFilter.FilterHPFBwhLvl1CutoffFreq1Hz)){
    ...
}
```

Or you can check all supported filters:

```ts
var filters: Array<SensorFilter> = sensor.getSupportedFilters();
```

###### Firmware mode

Information about the current mode of operation of the device firmware. It can be in two states:

- ModeBootloader - the device is in bootloader mode
- ModeApplication - normal operation

```ts
var mode: SensorFirmwareMode = sensor.getFirmwareMode()
...
// Setter supports only with Callibri MF
sensor.setFirmwareMode(SensorFirmwareMode.ModeApplication)
```

###### Sampling frequency

An property that is used to set or get the sample rate of a physiological signal. The higher the value, the more data flow from the device to the application, which means the higher the power consumption, but also the higher the range of measured frequencies. And there are also limitations on the physical communication channel (BLE) in terms of bandwidth.

Recommendations for choosing a value:

- For EEG signals not less than 250 Hz;
- For ECG signals 125 Hz;
- For EMG not less than 1000 Hz. When working with several devices at the same time, it is not recommended to increase the frequency above 1000 Hz;
- The breath channel has a fixed sampling rate of 20 Hertz. MEMS channels have a fixed sampling rate of 100 Hertz.

It is unchanged for BrainBit and BrainBitBlack and is 250 Hz. Can be changed for Signal Callibri/Kolibri and can take on the following values:

- 125 Hz
- 250 Hz
- 500 Hz
- 1000 Hz
- 2000 Hz

Not available for Callibi EMS. Dont use for NeuroEEG-M device, you need to use a 'setAmplifierParam()' method for it.
If you try to set an unsupported value to the device, an exception will be thrown.

```ts
var sf: SensorSamplingFrequency = sensor.getSamplingFrequency()
...
// Setter supports only with Callibri MF
sensor.setSamplingFrequency(SensorSamplingFrequency.FrequencyHz1000)
```

###### Gain

Gain of an ADC signal. The higher the gain of the input signal, the less noise in the signal, but also the lower the maximum amplitude of the input signal. For Callibi/Kolibri MF you can set the desired value. Not available for Callibi/Kolibri EMS. Dont use for NeuroEEG device, you need to use a 'setAmplifierParam()' method for it

- 1
- 2
- 3
- 4
- 6
- 8
- 12
- 24

> Gain parameter is unsupported by BrainBit 2 sensor

```ts
var gain: SensorGain = sensor.getGain()
...
// Setter supports only with Callibri MF or BrainBit
sensor.setGain(SensorGain.Gain3)
```

Available values for BrainBit: 1, 2, 3, 4, 6, 8, 12

If you try to set an unsupported value to the device, an exception will be thrown.

###### Offset

Signal offset. It is unchanged for BrainBit and BrainBitBlack and is 0. For Callibi/Kolibri MF you can set the desired value. Not available for Callibi/Kolibri EMS and NeuroEEG-M. 

- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8

```ts
var offset: SensorDataOffset = sensor.getDataOffset()
...
sensor.setDataOffset(SensorDataOffset.DataOffset0)
```

If you try to set an unsupported value to the device, an exception will be thrown.

###### ExternalSwitchState

Switched signal source. This parameter is available only to Callibi/Kolibri. It is can take on the following values:

- ExtSwInElectrodesRespUSB - Respiratory channel data source is USB connector. The source of myographic channel data are terminals.
- ExtSwInElectrodes - Terminals are the source of myographic channel data. The breathing channel is not used.
- ExtSwInUSB - The source of myographic channel data is the USB connector. The breathing channel is not used.
- ExtSwInRespUSB - Respiratory channel data source is USB connector. Myographic channel is not used.

```ts
var extSwInp: SensorExternalSwitchInput = sensor.getExtSwInput()
...
sensor.setExtSwInput(SensorExternalSwitchInput.ExtSwInElectrodes)
```

If you try to set an unsupported value to the device, an exception will be thrown.

###### ADC input state

State value of an ADC (Analog to Digital Converter) input of a device. This property is available only to Callibi/Kolibri. It is can take on the following values:

- Electrodes - Inputs to electrodes. This mode is designed to receive a physiological signal from the place of application.
- Short - Inputs are short-circuited. This mode is designed to close the outputs. The output will have noise at the baseline or 0 volt level.
- Test - Inputs to the ADC test. This mode is intended for checking the correctness of the ADC operation. The output should be a square wave signal with a frequency of 1 Hz and an amplitude of +/- 1 mV.
- Resistance - Inputs for measuring the interelectrode resistance. This mode is designed to measure the interelectrode resistance, as well as to obtain a physiological signal. This is the recommended default mode.

```ts
var input: SensorADCInput = sensor.getADCInput()
...
sensor.setADCInput(SensorADCInput.Electrodes)
```

If you try to set an unsupported value to the device, an exception will be thrown.

###### AccelerometerSens

The sensitivity value of the accelerometer, if the device supports it. This property is available only to Callibi/Kolibri. It is recommended to check the presence of the MEMS module before use. It is can take on the following values:

- 2g - Normal sensitivity. Minimum value. Sufficient for practical use
- 4g - Increased sensitivity.
- 8g - High sensitivity.
- 16g - Maximum sensitivity.

```ts
var accSens: SensorAccelerometerSensitivity = sensor.getAccSens()
...
sensor.setAccSens(SensorAccelerometerSensitivity.AccSens2g)
```

If you try to set an unsupported value to the device, an exception will be thrown.

###### GyroscopeSens

The gyroscope gain value, if the device supports it. This property is available only to Callibi/Kolibri. It is recommended to check the presence of the MEMS module before use. It is can take on the following values:

- 250Grad - The range of measured values of the angular velocity is from 0 to 2000 degrees per second. Recommended for measuring angles.
- 500Grad - The range of measured values of the angular velocity is from 0 to 1000 degrees per second.
- 1000Grad - The range of measured values of the angular velocity is from 0 to 500 degrees per second.
- 2000Grad - The range of measured values of the angular velocity is from 0 to 250 degrees per second.

```ts
var gyreSens: SensorGyroscopeSensitivity = sensor.getGyroSens()
...
sensor.setGyroSens(SensorGyroscopeSensitivity.GyroSens250Grad)
```

If you try to set an unsupported value to the device, an exception will be thrown.

###### StimulatorAndMAState

Parameter for obtaining information about the state of the stimulation mode and the motion assistant mode. This parameter is available only to Callibi/Kolibri EMS. Contains:

- StimulatorState - Stimulation mode state
- MAState - Drive assistant mode state

Each of the fields can be in three states:
 - Enabled
 - Disabled
 - NoParams

```ts
var maState: CallibriStimulatorMAState = sensor.getStimulatorMAState()
```

If you try to set an unsupported value to the device, an exception will be thrown.
 
###### StimulatorParamPack

Stimulation parameters. This property is available only to Callibi/Kolibri EMS. Contains:

- Current - stimulus amplitude in  mA. 1..100.
- PulseWidth - duration of the stimulating pulse by us. 20..460.
- Frequency - frequency of stimulation impulses by Hz. 1..200.
- StimulusDuration - maximum stimulation time by ms. 0...65535.

```ts
var param: CallibriStimulationParams = sensor.getStimulatorParam()
...
sensor.setStimulatorParam(CallibriStimulationParams.Frequency)
```

If you try to set an unsupported value to the device, an exception will be thrown.

###### Motion assistant parameters

Parameter for describing a stimulation mode, if the device supports this mode. This structure describes the parameters for starting the stimulation mode depending on the place of application of the device, the position of the limb in space and the pause between the starts of this mode while the specified conditions are met. Parameter available only for Callibi/Kolibri stimulator. Contain a structure named `CallibriMotionAssistantParams` with fields:

- GyroStart - Angle value in degrees at which the stimulation mode will start, if it is correctly configured.
- GyroStop - Angle value in degrees above which the stimulation mode will stop, if it is correctly configured.
- Limb - multiple of 10. This means that the device is using the (MinPauseMs / 10) value. Correct values: 10, 20, 30, 40 ... 
- MinPauseMs - Pause between starts of stimulation mode in milliseconds. 

```ts
var param: CallibriMotionAssistantParams = sensor.getMotionAssistantParam()
...
sensor.setMotionAssistantParam(CallibriMotionAssistantParams.GyroStart)
```

If you try to set an unsupported value to the device, an exception will be thrown.

###### Firmware version

Information about the device firmware version. Contain a structure named `SensorVersion` with fields:

- firmware major
- firmware minor
- firmware patch
- hardware major
- hardware minor
- hardware patch
- extension major

```ts
var version: SensorVersion = sensor.getVersion()
```

###### Motion counter parameters

This parameter is available only to Callibi/Kolibri. Contain a structure named `MotionCounterParamCallibri` with fields:

- InsenseThresholdMG - Insense threshold mg. 0..500
- InsenseThresholdSample - Algorithm insense threshold in time (in samples with the MEMS sampling rate) 0..500

```ts
var param: CallibriMotionCounterParam = sensor.getMotionCounterParam()
...
sensor.setMotionCounterParam(CallibriMotionCounterParam.InsenseThresholdMG)
```

If you try to set an unsupported value to the device, an exception will be thrown.

###### Motion counter

Contains the number of motions. This parameter is available only to Callibi/Kolibri. A numeric value that cannot be changed.

```ts
var counter: string = sensor.getMotionCounter()
```

###### Battery power

Battery power value. Integer value.

```ts
var power = sensor.getBattPower()
```

###### Sensor family

Type of device. Enumeration.

```ts
var family: SensorFamily = sensor.getSensFamily()
```

###### Sensor mode

Operating mode of the physiological amplifier. Parameter is available for BraibBitBlack and for NeuroEEG-M.

```ts
var mode: SensorAmpMode = sensor.getAmpMode()
```

###### Resistance sampling frequency

Frequency of updating resistance values. Immutable value. Not available for Callibri/Kolibri. Don't has a fixed value for BrainBit/BrainBitBlack. To get this frequency in NeuroEEG-M, it is required to use getAmplifierParam.

```ts
var freq: SensorSamplingFrequency = sensor.getSamplingFrequencyResist();
```

###### MEMS sampling frequency

Frequency of updating MEMS values. Immutable value. Available for Callibri/Kolibri supporting MEMS.

```ts
var freq: SensorSamplingFrequency = sensor.getSamplingFrequencyMEMS();
```

###### Respiration sampling frequency

Frequency of updating breath values. Immutable value. Available for Callibri/Kolibri supporting breath.

```ts
var freq: SensorSamplingFrequency = sensor.getSamplingFrequencyResp();
```

###### Envelope sampling frequency

Frequency of updating envelope values. Immutable value. Available for Callibri/Kolibri supporting envelope.

```ts
var freq: SensorSamplingFrequency = sensor.getSamplingFrequencyEnvelope();
```

##### Features

Each device has a specific set of modules. You can find out which modules the device has using the property `Feature`:

```ts
console.log(sensor.getFeatures().map(feature => SensorFeature[feature]))

// Output:
//
// ["Signal", "Resist"]
```

You can also check if the feature is supported, for example `Signal`:

```ts
if(sensor.isSupportedFeature(SensorFeature.Signal)){
    ...
}
```

##### Commands

The device can execute certain commands. The list of supported commands can be obtained as follows:

```ts
console.log(sensor.getCommands().map(command => SensorCommand[command]))

// Output:
//
// ["StartSignal", "StopSignal", ...]
```

And also check if the device can execute the desired command:

```ts
if(sensor.isSupportedCommand(SensorCommand.StartSignal)){
    ...
}
```

### BrainBit, BrainBitBlack

The BrainBit and BrainBitBlack is a headband with 4 electrodes and 4 data channels - O1, O2, T3, T4. The device has a frequency of 250 Hz, which means that data on each of the channels will come at a frequency of 250 samples per second. The parameters of this device, such as gain, data offset and the other, cannot be changed, if you try to do this, an exception will appear.

```ts
sensor.setName("newname") // <- This throw an exeption!
```

>  You can distinguish BrainBit device from Flex by the firmware version number: if the `SensorVersion.FwMajor` is more than 100 - it's Flex, if it's less than BrainBit.

> BrainBitBlack, unlike BrainBit, requires pairing with a PC/mobile device. So, before connecting to the BBB, you must put it into pairing mode. SDK starts the pairing process automatically.

#### 66Hz filter

The filter that removes noise at 66 Hz is enabled by default, but you can independently turn it off or turn it on if necessary by commands:

```ts
// disable filter
sensor.disable66HzFilter()

// enable filter
sensor.enable66HzFilter()
```

#### Receiving signal

To receive signal data, you need to subscribe to the corresponding callback. The values will be received as a packet from four channels at once, which will avoid desynchronization between them. The values come in volts. In order for the device to start transmitting data, you need to start a signal using the `execute` command. This method is also recommended to be run in an separate thread.

```ts
sensor.AddSignalReceived((data)=>{
    console.log(data)
}); 
sensor.execute(SensorCommand.StartSignal)
...
sensor.RemoveSignalReceived();
sensor.ExecuteCommand(SensorCommand.StopSignal)
```

You get signal values as a list of samples, each containing:
 - PackNum -  number for each packet
 - Marker - marker of sample, if it was sent and this feature is supported by the device
 - O1 - value of O1 channel in V
 - O2 - value of O2 channel in V
 - T3 - value of T3 channel in V
 - T4 - value of T4 channel in V

> NOTE:
> For BrainBit PackNum may be duplicated, although the data (O1-T4) are different. In this case we get 2 counts from BrainBit with the same packet number

#### Ping signal

Some devices support signal quality check functions using signal ping. You can send a specific value (marker) to the device and it will return that marker with the next signal data packet. Marker is small value one byte in size.

> Available only to BrainBitBlack

```ts
sensor.pingNeuroSmart(5)
```

#### Recieving resistance

BrainBit and BrainBitBlack also allow you to get resistance values. With their help, you can determine the quality of the electrodes to the skin. Initial resistance values are infinity. The values change when the BB is on the head.

For BrainBit the upper limit of resistance is 2.5 ohms.

```ts
sensor.AddResistanceReceived((data)=>{
    console.log(data)
}); 
sensor.execute(SensorCommand.StartResist)
...
sensor.RemoveResistanceReceived();
sensor.execute(SensorCommand.StopResist)
```

You get resistance values structure of samples for each channel:
 - O1 - value of O1 channel in Ohm
 - O2 - value of O2 channel in Ohm
 - T3 - value of T3 channel in Ohm
 - T4 - value of T4 channel in Ohm

### Callibri MF, Kolibri MF

The Callibri family of devices has a wide range of built-in modules. For each of these modules, the SDK contains its own processing area. It is recommended before using any of the modules to check if the module is supported by the device using one of the methods `isSupportedFeature`, `isSupportedCommand` or `isSupportedParameter`

#### Receiving signal

To receive signal data, you need to subscribe to the corresponding callback. The values come in volts. In order for the device to start transmitting data, you need to start a signal using the `execute` command.

The sampling rate can be controlled using the `SamplingFrequency` property. For example, at a frequency of 1000 Hz, the device will send 1000 samples per second. Supports frequencies 125/250/500/1000/2000 Hz. You can also adjust the signal offset (`DataOffset`) and signal power (`Gain`).

```ts
sensor.AddSignalReceived((data)=>{
    console.log(data)
}); 
sensor.execute(SensorCommand.StartSignal)
...
sensor.RemoveSignalReceived();
sensor.execute(SensorCommand.StopSignal)
```

You get signal values as a list of samples, each containing:
 - PackNum -  number for each packet
 - array of samples in V


#### Signal settings

By default, the Callibri/Kolibri gives a signal without filters. In order to receive a certain type of signal, for example, EEG or ECG, you need to configure the device in a certain way. For this there is a property `SignalTypeCallibri`. Preset signal types include:
 - EEG - parameters: Gain6, Offset = 3,  ADCInputResistance
 - EMG - parameters: Gain6, Offset = 3,  ADCInputResistance
 - ECG - parameters: Gain6, Offset = 3,  ADCInputResistance
 - EDA (GSR) - parameters: Gain6, Offset = 8,  ADCInputResistance, ExternalSwitchInput.MioElectrodes. By default the input to the terminals is set. If you want to change it to USB use the `ExtSwInput` property.
 - TenzoBreathing - parameters: Gain8, Offset = 8,  ADCInputResistance, SensorExternalSwitchInput.ExtSwInUSB
 - StrainGaugeBreathing - parameters: Gain6, Offset = 4,  ADCInputResistance, ExternalSwitchInput.ExtSwInElectrodes
 - ImpedanceBreathing - parameters: Gain6, Offset = 4,  ADCInputResistance, ExternalSwitchInput.ExtSwInRespUSB

Hardware filters disabled by default for all signal types. You can enable filters by `HardwareFilters` property, for example LP filter. 

> Important!
> When using an LP filter in the sensor, you will not see the constant component of the signal.

```ts
var signalType = sensor.getSignalType()
...
sensor.setSignalType(CallibriSignalType.ECG)
```


#### Receiving envelope

To get the values of the envelope, you need to subscribe to a specific event and start pickup. The channel must be configured in the same way as for a normal signal, and all parameters work the same way. Then the signal is filtered and decimated at 20 Hz.

```ts
sensor.AddEnvelopeDataChanged((data)=>{
    console.log(data)
}); 
sensor.execute(SensorCommand.StartEnvelope)
...
sensor.RemoveEnvelopeDataChanged();
sensor.execute(SensorCommand.StopEnvelope)
```

You get signal values as a list of samples, each containing:
 - PackNum - number for each packet
 - sample in V

#### Check electrodes state

Allows you to determine the presence of electrical contact of the device electrodes with human skin. It can be in three states:
 - Normal - The electrodes have normal skin contact. Low electrical resistance between electrodes. The expected state when working with physiological signals.
 - Detached - High electrical resistance between electrodes. High probability of interference in the physiological signal.
 - HighResistance - There is no electrical contact between the electrodes of the device.
 
To receive data, you need to subscribe to the corresponding callback and start signal pickup.

```ts
sensor.AddElectrodeStateChanged((data)=>{
    console.log(data)
}); 
sensor.execute(SensorCommand.StartSignal)
...
sensor.RemoveElectrodeStateChanged();
sensor.execute(SensorCommand.StopSignal)
```

You get signal values as a list of samples, each containing:
 - PackNum - number for each packet
 - sample in V

#### Receiving Respiration

The breathing microcircuit is optional on request. Its presence can be checked using the `IsSupportedFeature` method. To receive data, you need to connect to the device, subscribe to the notification of data receipt and start picking up.

```ts
if(sensor.isSupportedFeature(SensorFeature.Respiration))
{
    sensor.AddRespirationChanged((data)=>{
        console.log(data)
    }); 
    sensor.execute(SensorCommand.StartRespiration)
    ...
    sensor.RemoveRespirationChanged();
    sensor.execute(SensorCommand.StopRespiration)
}
```

You get signal values as a list of samples, each containing:
 - PackNum - number for each packet
 - array of samples in V

#### MEMS

The MEMS microcircuit is optional on request. Its presence can be checked using the `IsSupportedFeature` method. This means that the device contains an accelerometer and a gyroscope. Contains information about the position of the device in space. Channel sampling frequency is 100 Hz.

MEMS data is a structure:

- PackNum - number for each packet
- Accelerometer - accelerometer data. Contains:
  - X - Abscissa Acceleration
  - Y - Y-axis acceleration
  - Z - Acceleration along the applicate axis
- Gyroscope - gyroscope data
  - X - The angle of inclination along the abscissa axis
  - Y - Inclination angle along the ordinate axis
  - Z - Angle of inclination along the axis of the applicate

Quaternion data is a structure:

- PackNum - number for each packet
- W - Rotation component
- X - Vector abscissa coordinate
- Y - Vector coordinate along the ordinate axis
- Z - The coordinate of the vector along the axis of the applicate

It is recommended to perform calibration on a flat, horizontal non-vibrating surface before starting work using the `CalibrateMEMS` command. Calibration state can be checked using the `MEMSCalibrateState` property, it can take only two values: calibrated (true), not calibrated (false).

> MEMS and quaternion available only to Callibri/Kolibri MF!

```ts
// For receiving MEMS
sensor.AddMMEMSDataReceived((data)=>{
    console.log(data)
})
sensor.execute(SensorCommand.StartMEMS)
...
sensor.RemoveMEMSDataReceived()
sensor.execute(SensorCommand.StopMEMS)

// For quarternion
sensor.AddQuaternionDataReceived((data)=>{
    console.log(data)
})
sensor.execute(SensorCommand.StartAngle)
...
sensor.RemoveQuaternionDataReceived()
sensor.execute(SensorCommand.StopAngle)
```

#### Motion counter

Parameters for motion counter. You can configure it with the `CallibriMotionCounterParam` property, in it:

 - InsensThreshmG - Threshold of the algorithm's deadness in amplitude (in mg). The maximum value is 500mg. The minimum value is 0.
 - InsensThreshSamp - Threshold of the algorithm's insensitivity in time (in samples with the MEMS sampling rate). The maximum value is 500 samples. The minimum value is 0.

You can find out the current number of movements using the `MotionCounter` property. You can reset the counter with the `ResetMotionCounter` command. No additional commands are needed to start the counter, it will be incremented all the time until the reset command is executed.

```ts
if(sensor.isSupportedParameter(SensorParameter.MotionCounter)
{
    sensor.setMotionCounterParam({
        InsenseThresholdMG: 250, InsenseThresholdSample:250
    })
    var motionCount = sensor.getMotionCounter()
    sensor.execute(SensorCommand.ResetMotionCounter)
}

```

### Callibri/Kolibri EMS

Callibri is a EMS if it supports the stimulation module:

```ts
var isStimulator = sensor.isSupportedFeature(SensorFeature.CurrentStimulator)
```

#### Stimulation

Before starting the session, you need to correctly configure the device, otherwise the current strength may be too strong or the duration of stimulation too long. The setting is done using the `StimulatorParamCallibri` property. You can set the following options:

 - Current - stimulus amplitude in  mA. 1..100
 - PulseWidth - duration of the stimulating pulse by us. 20..460
 - Frequency - frequency of stimulation impulses by Hz. 1..200.
 - StimulusDuration - maximum stimulation time by ms. 0...65535. Zero is infinitely.

You can start and stop stimulation with the following commands:

```ts
sensor.execute(SensorCommand.StartCurrentStimulation)
...
sensor.execute(SensorCommand.StopCurrentStimulation)
```

> Stimulation does not stop after the `StimulusDuration` time has elapsed.

You can check the state of stimulation using the `StimulatorMAState` property. Contains two parameters:

- StimulatorState - Stimulation mode state
- MAState - Drive assistant mode state

Each of the parameters can be in 4 states:

- StimStateNoParams - parameter not set
- StimStateDisabled - mode disabled
- StimStateEnabled - mode enabled
- StimStateUnsupported - sensor unsupported

#### Motion assistant

The Callibri EMS, which contains the MEMS module, can act as a motion corrector. You can set the initial and final angle of the device and the limb on which the Callibri/Kolibri is installed, as well as a pause between stimulations and turn on the motion assistant. All the time while the device is tilted in the set range, stimulation will met. Stimulation will take place according to the settings of `StimulatorParam`.

The motion corrector works in the background. After turning on the motion assistant mode, it will work regardless of the connection to a mobile device/PC. You can turn on the motion corrector mode using a special command. When the device is rebooted, it is also reset.

Motion corrector parameters are a structure with fields:

 - GyroStart - Angle value in degrees at which the stimulation mode will start, if it is correctly configured.
 - GyroStop - Angle value in degrees above which the stimulation mode will stop, if it is correctly configured.
 - Limb - overlay location in stimulation mode, if supported.
 - MinPauseMs - Pause between starts of stimulation mode in milliseconds. Multiple of 10. This means that the device is using the (MinPauseMs / 10) value. Correct values: 10, 20, 30, 40 ... 

```ts
sensor.setMotionAssistantParam({
    GyroStart: 45, 
    GyroStop:10, 
    Limb: CallibriMotionAssistantLimb.RightLeg, 
    MinPauseMs: 10
 })
sensor.execute(SensorCommand.EnableMotionAssistant)
...
sensor.execute(SensorCommand.StopCurrentStimulation)
```

### NeuroEEG-M

NeuroEEG-M requires pairing with a PC/mobile device. So, before connecting to device, you must put it into pairing mode. SDK starts the pairing process automatically.

Allows for long-term monitoring of brain biopotentials through 21 channels, with parallel registration of three polygraphic channels: ECG, EMG and EOG.

NeuroEEG-M device supports the next signal frequencies:
 - 1000 Hz
 - 500 Hz
 - 250 Hz

And gain values:
 - 1
 - 2
 - 4
 - 6
 - 8
 - 12
 - 24


#### Info about channels

NeuroEEG device has 24 channels. You can get channels count by `getChannelsCount()` method or check constant value `NeuroEEGSensor.getMaxChCount()`. Get channels count:

```ts
let maxChCount: number = NeuroEEGSensor.getMaxChCount()

let chCount: number = sensor.getChannelsCount()
```

Receive supportes channels info:
```ts
let channels: Array<EEGChannelInfo> = getSupportedChannels()
```

`EEGChannelInfo` contains some info:
 - Id - `EEGChannelId` type - physical location of the channel. Possible values:
  - O1 
  - P3 
  - C3 
  - F3 
  - Fp1
  - T5 
  - T3 
  - F7 
  - F8 
  - T4 
  - T6 
  - Fp2
  - F4 
  - C4 
  - P4 
  - O2 
  - D1 
  - D2 
  - OZ 
  - PZ 
  - CZ 
  - FZ 
  - FpZ
  - D3 
 - ChType - `EEGChannelType` type - type of channel, possible values A1, A2, differential or referent
 - Name - `String` type - channel name
 - Num - `number` type - channel number. By this number the channel will be located in the array of signal or resistance values

#### AmpMode

This device can show it's current amplifier mode. It can be in the following states:

  - Invalid
  - PowerDown
  - Idle
  - Signal
  - Resist
  - SignalResist
  - Envelope

You can check amp. mode by two ways:

1. by callback:

```ts
sensor.AddAmpModeChanged((ampMode)=>
  { 
    console.info("ampMode: " + ampMode) 
  });
```

2. get value at any time:

```ts
var mode: SensorAmpMode = sensor.getAmpMode()
```

It is very important parameter for NeuroEEG-M device because you can set amplifier parameters only if device into `PowerDown` or `Idle` mode.

#### Amplifier parameters

You can configure each channel and whole device settings by setting amplifier parameters.

```ts
let maxChCount = NeuroEEGSensor.getMaxChCount();

let ampParam: NeuroEEGAmplifierParam = {
  ReferentResistMesureAllow: false,
  Frequency: SensorSamplingFrequency.FrequencyHz500,
  ReferentMode: EEGRefMode.A1A2,
  ChannelMode: Array(maxChCount).fill(EEGChannelMode.EEGChannelModeSignalResist),
  ChannelGain: Array(maxChCount).fill(SensorGain.Gain6)
};
sensor.setAmplifierParam(ampParam)

let result: NeuroEEGAmplifierParam = sensor.getAmplifierParam();
```

Channel modes:
 - SignalResist - device will be sent signal and resist values simultaneously
 - Signal - device will be sent only signal values, channel resistance will not be measured even if the resistance measurement mode is started in the device
 - Shorted - channel is shorted to ground, this mode can be used to analyze intrinsic noise of the device
 - Test - this channel will receive a test signal
 - Off - channel is disabled, no data from it

Referent modes:
 - A1A2 - both A1 and A2 references are available
 - HeadTop - only one reference is available, the resistance data is placed in field A1

ReferentResistMesureAllow - flag, allows resistance measurement by references (if true, the signal is not valid)

#### Receiving signal

To receive signal data, you need to subscribe to the corresponding callback. The values come in volts. In order for the device to start transmitting data, you need to start a signal using the `execute` command. This method is also recommended to be run in an separate thread.

The sampling rate can be controlled using the `Frequency` value of amplifier parameters. For example, at a frequency of 1000 Hz, the device will send about 1000 samples per second. Supports frequencies 250/500/1000 Hz. You can also adjust signal power (`Gain`) value for each channel.

```ts
sensor.AddSignalDataReceived((data)=>{
    console.log(data)
}); 
sensor.execute(SensorCommand.StartSignal)
...
sensor.RemoveSignalDataReceived();
sensor.execute(SensorCommand.StopSignal)
```

You get signal values as a list of samples, each containing:
 - PackNum - number for each packet
 - Marker - marker of sample
 - Samples - array of samples in V. Each sample number into array consistent with `Num` value of `EEGChannelInfo` from `getSupportedChannels()` method.

#### Receiving resistance

NeuroEEG-M also allow you to get resistance values. With their help, you can determine the quality of the electrodes to the skin. Initial resistance values are infinity. The values change when the device is on the head.

```ts
sensor.AddResistDataReceived((data)=>{
    console.log(data)
}); 
sensor.execute(SensorCommand.StartResist)
...
sensor.RemoveResistDataReceived();
sensor.execute(SensorCommand.StopResist)
```

You get resistance values structure of samples for each channel:
 - PackNum - number for each packet
 - A1 - value of A1 channel in Ohm
 - A2 - value of A2 channel in Ohm
 - Bias - value of Bias channel in Ohm
 - Values - array of values in Ohm. Each sample number into array consistent with `Num` value of `EEGChannelInfo` from `getSupportedChannels()` method.

#### Receiving signal and resistance

This device supports capturing signal and resistance at the same time. 

> NOTE:
> In this mode resistData may not arrive every update of the SignalResistReceived callback.

```ts
sensor.AddSignalResistReceived((signalData, resistData)=>{

}); 
sensor.execute(SensorCommand.StartSignalAndResist)
...
sensor.RemoveSignalResistReceived();
sensor.execute(SensorCommand.StopSignalAndResist)
```

#### Flash drive operation

##### Enable file system

Before any operations with a flash drive, you should check if the flash drive operation mode is enabled, and if it is not enabled - enable it:

```ts
let fsStatus: NeuroEEGFSStatus = sensor.getFSStatus();
if (fsStatus.Status != SensorFSStatus.FSSOK) {
  sensor.execute(SensorCommand.FileSystemEnable);
}
```

##### Info about file system

1. Read disk free space:

```ts
let info: SensorDiskInfo = sensor.getFSDiskInfo()
```

`SensorDiskInfo` contains two fields:

- TotalSize - total disk space
- FreeSize - free disk space

2. read info about all files or one file by name:

```ts
// read all file infos
let fileInfos: Array<SensorFileInfo> = sensor.readFileInfoAll(128)

// read file info by name
let fileInfo: SensorFileInfo = sensor.readFileInfo("my_file.txt")
```

`SensorFileInfo` contains:
- FileName - file name, max name length is 64
- FileSize - file size in bytes
- ModifiedYear, ModifiedMonth, ModifiedDayOfMonth, ModifiedHour, ModifiedMin, ModifiedSec - last modified date
- Attribute - 

> The month number is represented in the format 0-11, where january is 0 and december is 11

##### File operations

1. reading:

```ts
// read file info by name
let fileInfo: SensorFileInfo = sensor.readFileInfo("my_file.txt")

// read file data
let fileData: Uint8Array = await sensor.readFile(fileInfo.FileName, fileInfo.FileSize);

// then convert data to your format
```

2. writing:

```ts
let data: Uint8Array = // your data
let result: String = await sensor.writeFile("my_file.txt", data, 0);
```

Reading and writing to files is done via byte arrays and specifying their size, so any structure should be converted to this format before writing, and converted back to the format you need when reading.

> Note that the file name with the extension must not exceed 13 characters!

3. removing:

```ts
await sensor.deleteFile("my_file.txt");
```

##### Automatic survey recording

This mode is intended for data recording in standalone mode - when the device is disconnected from the receiver. this mode is intended for data recording in standalone mode - when the device is disconnected from the receiver. Before using this mode, it is necessary to enable interaction with the file system in the device using the following method `await sensor.execute(SensorCommand.FileSystemEnable);`.

You need to enable automatic writing to a file and specify a file name:

```ts
sensor.fileStreamAutosave("file.txt");
```

After writing is complete, you can read and parse the contents of the file as follows:

1. add a colback to read a portion of the data, since the survey file is quite large, and save all the received data into one object:

```ts
sensor.AddFileStreamDataReceived((fileData: SensorFileData[])=>{ console.info("fileData " + fileData) });
```

`SensorFileData` contains:
- OffsetStart - the offset of this data portion from the beginning in bytes
- DataAmount - total number of bytes remaining
- Data - readed bytes

Once the entire file has been read, it must be converted to signal and resistance data. To do this, you need to specify the amplifier parameters that were used when the file was recorded.

```ts
let readedData: Uint8Array = new Uint8Array(0);
let readedBytes: number = 0;
let ampParam: NeuroEEGAmplifierParam = {
  ReferentResistMesureAllow: false,
  Frequency: SensorSamplingFrequency.FrequencyHz500,
  ReferentMode: EEGRefMode.A1A2,
  ChannelMode: Array(maxChCount).fill(EEGChannelMode.EEGChannelModeSignalResist),
  ChannelGain: Array(maxChCount).fill(SensorGain.Gain6)
}; // <- specify your params

sensor.AddFileStreamDataReceived((fileData)=>
  { 
    fileData.forEach(v => {
      for (var _i = 0; _i < v.Data.length; _i++) {
        readedData[v.OffsetStart + _i] = v.Data[_i] as number;
      }
      readedBytes += v.Data.length;
    })
  }
);

// converting data
NeuroEEGSensor.StartProcessingData(ampParam);
let offset = 0;
let tmpCnt = 500; // <- you must specify the minimum packet size to process, this is 158 bytes. For simplicity, you can take 500 or more
while(offset != readedBytes){
  let cntBytes = offset + tmpCnt;
  if(cntBytes > readedBytes){
    cntBytes = readedBytes;
  }
  let processedData: ProcessSignalResult = await NeuroEEGSensor.ParseRawSignal(readedData.slice(offset, cntBytes)); // <- converted data will be written there
  offset += processedData.SzReady;
  console.log("Readed: " + processedData.SzReady + ", signal cnt: " + processedData.Signal.length + ", resist cnt: " + processedData.Resist.length);
}
NeuroEEGSensor.StopProcessingData();
```

To speed up processing, you can also convert data while reading, but then be sure to watch the minimum size of the arrays.

### BrainBit 2

The BrainBit2 class is designed to work with several device families: BrainBit 2, BrainBit Pro, BrainBit Flex, BrainBit Flex Pro. All devices have a sampling frequency of 250Hz. All devices can work in two modes - signal and resistance separately. These devices have different number of channels - BrainBit2, BrainBit Flex have 4 channels each and BrainBitPro, BrainBit FlexPro have 8 channels each. The main difference from BraibBit of the first version is that they do not support gain property, but have the ability to set gain for each channel separately using `BrainBit2AmplifierParam` structure.

#### 66Hz filter

The filter that removes noise at 66 Hz is enabled by default, but you can independently turn it off or turn it on if necessary by commands:

```ts
// disable filter
sensor.disable66HzFilter()

// enable filter
sensor.enable66HzFilter()
```

#### Info about channels

The device can have 4 or 8 channels. To determine how many and which channels they are, you need to use the `getSupportedChannels()` method:

```ts
let channels: Array<EEGChannelInfo> = getSupportedChannels()
```

`EEGChannelInfo` contains some info:
 - Id - `EEGChannelId` type - physical location of the channel. Possible values:
  - Unknown
  - O1 
  - P3 
  - C3 
  - F3 
  - Fp1
  - T5 
  - T3 
  - F7 
  - F8 
  - T4 
  - T6 
  - Fp2
  - F4 
  - C4 
  - P4 
  - O2 
  - D1 
  - D2 
  - OZ 
  - PZ 
  - CZ 
  - FZ 
  - FpZ
  - D3 

> IIn most cases, you will receive the values `O1`, `O2`, `T3`, `T4` or `Unknown`. `Unknown` means that the position of a specific electrode is free.

 - ChType - `EEGChannelType` type - type of channel, possible values `A1`, `A2`, `Differential` or `Referent`
 - Name - `String` type - channel name
 - Num - `number` type - channel number. By this number the channel will be located in the array of signal or resistance values

Also you can check only channels count without info:

```ts
let maxChCount: number = BrainBit2Sensor.getMaxChCount()

let chCount: number = sensor.getChannelsCount()
```

#### AmpMode

This device can show it's current amplifier mode. It can be in the following states:

  - Invalid
  - PowerDown
  - Idle
  - Signal
  - Resist
  - SignalResist
  - Envelope

You can check amp. mode by two ways:

1. by callback:

```ts
sensor.AddAMPModeChanged((ampMode)=>
  { 
    console.info("ampMode: " + ampMode) 
  });
```

2. get value at any time:

```ts
var mode: SensorAmpMode = sensor.getAmpMode()
```

It is very important parameter for BrainBit2 device because you can set amplifier parameters only if device into `PowerDown` or `Idle` mode.

#### Amplifier parameters

You can configure each channel and whole device settings by setting amplifier parameters.

```ts
let chCount = sensor.getChannelsCount();

let ampParam: BrainBit2AmplifierParam = {
  Current: GenCurrent.GenCurr6nA,
  ChSignalMode: Array(chCount).fill(BrainBit2ChannelMode.ChModeNormal),
  ChResistUse: Array(chCount).fill(true),
  ChGain: Array(chCount).fill(SensorGain.Gain3),
};
sensor.setAmplifierParam(ampParam)
```

Current - setting parameters of the probe current generator
 - GenCurr0nA 
 - GenCurr6nA 
 - GenCurr12nA
 - GenCurr18nA
 - GenCurr24nA
 - GenCurr6uA 
 - GenCurr24uA
 - Unsupported

Signal modes:
 - Short - shorted input
 - Normal - bipolar input mode (used for EEG)

Gain - gain of an ADC signal for each channel.

If you do not want to set all parameters, but change only one, for example Gain, it is recommended to read the current parameters of the device and change the desired parameter:

```ts
let chCount = sensor.getChannelsCount();

var ampParamp = sensor.getAmplifierParam();
ampParam.ChGain = Array(chCount).fill(SensorGain.Gain3);
sensor.setAmplifierParam(ampParam);
```

> NOTE:
> Recommendation for Gain. Set to SensorGain.Gain3.

#### Receiving signal

To receive signal data, you need to subscribe to the corresponding callback. The values come in volts. In order for the device to start transmitting data, you need to start a signal using the `execute` command. This method is also recommended to be run in an separate thread.

```ts
sensor.AddSignalReceived((data)=>{
    console.log(data)
}); 
sensor.execute(SensorCommand.StartSignal)
...
sensor.RemoveSignalReceived();
sensor.execute(SensorCommand.StopSignal)
```

You get signal values as a list of samples, each containing:
 - PackNum - number for each packet
 - Marker - marker of sample
 - Samples - array of samples in V. Each sample number into array consistent with `Num` value of `EEGChannelInfo` from `getSupportedChannels()` method.

#### Receiving resistance

BrainBit2 also allow you to get resistance values. With their help, you can determine the quality of the electrodes to the skin. Initial resistance values are infinity. The values change when the device is on the head.

```ts
sensor.AddResistanceReceived((data)=>{
    console.log(data)
}); 
sensor.execute(SensorCommand.StartResist)
...
sensor.RemoveResistanceReceived();
sensor.execute(SensorCommand.StopResist)
```

You get resistance values structure of samples (`ResistRefChannelsData`) for each channel:
 - PackNum - number for each packet
 - Samples - array of values in Ohm. Each sample number into array consistent with `Num` value of `EEGChannelInfo` from `getSupportedChannels()` method.
 - Referents - array of values for referents channels. For BrainBit2 sensor is empty now.

