BrainBit foe developers Visit website

Tutorial Swift


Platform requirements

OS: MacOS Mojave

Software: Xcode 10.2

IOS minimal version: 11.0

Framework: neurosdk.framework-1.4.5

Dependencies: libc++.tbd, CoreBluetooth.framework


Adding Frameworks to Your Xcode Project

  1. Select the project file from the project navigator on the left side of the project window.
  2. Select the target for where you want to add frameworks in the project settings editor.
  3. Select the “Build Phases” tab, and click the small triangle next to “Link Binary With Libraries” to view all of the frameworks in your application.
  4. To Add frameworks, click the “+” below the list of frameworks.
  5. To select multiple frameworks, press and hold the command key while using the mouse to click the desired frameworks.

Scanning for devices

To find nearby devices use NTDeviceScanner

let scanner = NTDeviceScanner() // default constructor for Any DeviceType
 scanner.subscribeFoundDevice { [weak self] (deviceInfo) in
     let device = NTDevice(deviceInfo)

 subscribeFoundDevice event will hit when a new device appears.

Connecting to the device

To receive data from the device and to send commands to it first you need to connect to it


You could read the device state to check whether it is connected or not. You also could subscribe subscribeParameterChanged event to receive notifications when the device goes out of range.

device?.subscribeParameterChanged(subscriber: { (param) in
          if(param == .State) {
               let state = safe.device?.readParam(param: .State) as NTState? 

When the device is connected you could read lists of supported parameters, signal channels, available commands. You could read the device name and address in string format and firmware version.

let state = safe.device?.readParam(param: .State) as NTState?
let name = safe.device?.readParam(param: .Name) as String?
let address = safe.device?.readParam(param: .Address) as String?

To get a list of command and channels use appropriate properties.

for channel in device?.channels() {
   //Your code here
for command in device?.commands() {
   //Your code here

Retrieving signal data

For Brainbit device, actual channels are Signal, Battery and Resistance. To get channel records from the device with a specific type, DeviceTraits class could be used. To subscribe for new data notifications Use subscribeLengthChanged method of channel class. There are four commands for managing device measuring state: StartSignal, StopSignal, StartResist, StopResist.

if NTDeviceTraits.HasChannelsWithType(device, channelType: .TypeBattery)
   batteryChannel = NTBatteryChannel(device)
if NTDeviceTraits.HasChannelsWithType(device, channelType: .TypeConnectionStats) {
   let connectionStatsChannelInfo = NTDeviceTraits.GetChannelsWithType(device, channelType: .TypeConnectionStats)?.first
   statsChannel = NTConnectionStatsChannel(device, channelInfo: connectionStatsChannelInfo!)

if NTDeviceTraits.HasChannelsWithType(device, channelType: .TypeSignal)
  let channelInfo = NTDeviceTraits.GetChannelsWithType(device, channelType: .TypeSignal)?.first
  self.signal = NTEegChannel(self.device!, channelInfo)

Battery data channel contains data as int values, Resistance and Signal channels as double values. Write callback methods to handle new data. Information about the channel which triggered a notification.

self.batteryChannel.subscribeLengthChanged(subscribe: { length in
     let level = channel.readData(offset: length-1, length: 1)?.first

self.signal.subscribeLengthChanged(subscribe: { (length) in
     let newdata = self.signal?.readData(offset: length-1, length: 1)?.first

Channel buffers collection

There is a set of different channel buffers for storing and processing signal data. All channel buffers need to be disposed after work is finished.

//Resistance channel. Receives and stores information about the resistance of electrodes
let resistanceChannel = NTResistanceChannel(device, info)

//Bipolar channel. Calculates the difference between two EEG (or simple signal) channels. 
//Could be used to reduce some types of artifacts
let bipolarChannel = NTBipolarDoubleChannel(eegChannel1, eegChannel2);

//Spectrum channel. Calculates signal spectrum for a selected signal region.
//readData returns array with spectrum samples of length provided in SpectrumLength property
//offset and length parameters relate to source signal channel which was used to make spectrum channel
let spectrumChannel = NTSpectrumChannel(eegChannel1, .WindowBlackman)
let frequencyStep = spectrumChannel.hzPerSpectrumSample()

//Spectrum power channel. Calculates and stores a power of spectrum on a selected frequency band
//You could use several spectrum channels for spectrum power calculation. Results will be joined into one
let spectrumPowerChannel = NTSpectrumPowerDoubleChannel([NTSpectrumChannel()],  
                             lowFreq: lowFrequency, highFreq: highFrequency, 
                             name: "SpectrumPower", duration: 250, 
                             overlapping: 2000)

Emulation of device

If you don’t have Brainbit device yet, you could try all signal processing features using emulation channel. You need to provide spectral components of an emulation signal to create this channel. You could use this channel for all calculations that receive channels of doubles.

let emulationChannel = NTEmulationDoubleChannel(
                  components: [NTEmulationSine(amplV: 100e-6, freq: 10, phase: 0)], 
                  sample_freq: 250, lendgth: 2000) //8 seconds of 

emulationChannel.subscribeLengthChanged(subscribe: { (length) in
     // new data
emulationChannel.startTimer(); //begins emulation of receiving new signal