BrainAccess Core C API Usage Example
// This is the main file for a Bluetooth EEG system application, connection
// example. It includes necessary headers, defines sleep functions, and
// initializes variables.
#include "bacore.h"
#include "eeg_manager.h"
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h> // Windows-specific sleep function
#define sleep_ms(x) Sleep(x)
#else
#include <unistd.h> // POSIX (Linux/Unix) sleep function
#define sleep_ms(x) usleep((x) * 1000) // usleep takes microseconds
#endif
#define DEVICE_NAME "BA MINI 000"
#define CHANNELS_COUNT 8
ba_eeg_manager* manager1;
ba_error compatibility;
void ota_update_callback(void* data, const size_t size, const size_t sent)
{
printf("update: %zu / %zu\n", size, sent);
}
static void chunk_callback(const void* const* data, size_t size, void* user_data)
{
// Get the data for the sample number and channels
const size_t* eeg_data_sample_number = (const size_t*)data[ba_eeg_manager_get_channel_index(manager1, BA_EEG_CHANNEL_ID_SAMPLE_NUMBER)];
const double* eeg_data_channel_0 = (const double*)data[ba_eeg_manager_get_channel_index(manager1, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 0)];
const double* eeg_data_channel_1 = (const double*)data[ba_eeg_manager_get_channel_index(manager1, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 1)];
const double* eeg_data_channel_2 = (const double*)data[ba_eeg_manager_get_channel_index(manager1, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 2)];
const double* eeg_data_channel_3 = (const double*)data[ba_eeg_manager_get_channel_index(manager1, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 3)];
const double* eeg_data_channel_4 = (const double*)data[ba_eeg_manager_get_channel_index(manager1, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 4)];
const double* eeg_data_channel_5 = (const double*)data[ba_eeg_manager_get_channel_index(manager1, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 5)];
const double* eeg_data_channel_6 = (const double*)data[ba_eeg_manager_get_channel_index(manager1, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 6)];
const uint8_t* is_streaming = (const uint8_t*)data[ba_eeg_manager_get_channel_index(manager1, BA_EEG_CHANNEL_ID_STREAMING)];
for (size_t i = 0; i < size; ++i)
{
// Process the data directly without storing it in a structure
// printf("[%zu] %f - %f - %f - %f || %d\n", eeg_data_sample_number[i], eeg_data_channel_0[i], eeg_data_channel_1[i], eeg_data_channel_2[i], eeg_data_channel_3[i], is_streaming[i]);
}
// printf("\n");
}
// Callback function for handling disconnection events.
// This function is called when the connection to the device is lost.
// It prints a message indicating the disconnection event.
void disconnect_callback(void* data)
{
printf("Disconnectedd\n");
}
// Function to scan for available Bluetooth EEG devices and initialize the
// system.
ba_init_error scan_devices()
{
// Initialize the status variable to hold the result of the initialization
ba_init_error status = BA_INIT_ERROR_OK;
const ba_version* curr_version = ba_core_get_version();
printf("Core current version : %d.%d.%d\n", curr_version->major, curr_version->minor, curr_version->patch);
// Initialize the Bluetooth EEG system using the defined version
status |= ba_core_init();
// Check if the initialization was successful
if (status != BA_INIT_ERROR_OK)
{
// Print an error message if the initialization failed
printf("Core init Error: %d\n", status);
return status;
}
// Scan for available Bluetooth EEG devices
status |= ba_core_scan(0);
// Check if no devices were found after the first scan
if (ba_core_device_count() == 0)
{
// Keep scanning for devices until at least one is found
for (int i = 0; i < 5; i++)
{
// Print the number of scan attempts
printf("Found devices count: %d\n", ba_core_device_count());
// Scan for available devices again
status |= ba_core_scan(0);
if (ba_core_device_count() != 0)
{
break;
}
}
}
// Print a message indicating the end of the scanning process
printf("Search: \n");
// Check if no devices were found after scanning
if (ba_core_device_count() == 0)
{
// Print a message indicating that no devices were found
printf("0 Devices were found\n");
// Close the Bluetooth EEG system
ba_core_close();
// Return an error code indicating that no devices were found
status |= BA_INIT_ERROR_NOT_FOUND;
}
return status;
}
// Function to connect to the Bluetooth EEG device and perform EEG operations
ba_init_error connect_ble(ba_eeg_manager** const manager, const char* device_name)
{
ba_init_error status = BA_INIT_ERROR_OK;
// Print the number of available devices
printf("devices found: %d\n", ba_core_device_count());
// Get the name of the first device
char name[20];
// Find the device with the name "BA MINI 002"
int device = -1;
for (int i = 0; i < ba_core_device_count(); ++i)
{
ba_core_device_get_name(name, i);
if (strcmp(name, device_name) == 0)
{
device = i;
printf("Device found!!!!!!!\n");
}
}
// If the device is not found, return -1
if (device < 0)
{
return -1;
}
// Define the callback function for handling disconnection events
ba_callback_disconnect disconnect_cb = disconnect_callback;
// Set the callback function for handling disconnection events
ba_eeg_manager_set_callback_disconnect(*manager, disconnect_cb, NULL);
// Connect to the selected device
compatibility = ba_eeg_manager_connect(*manager, device, NULL, NULL);
printf("Connected\n");
printf("device info: %zu\n", ba_eeg_manager_get_device_info(manager)->serial_number);
if (compatibility == BA_ERROR_CONNECTION)
{
return status;
}
const ba_battery_info info = ba_eeg_manager_get_battery_info(*manager);
printf("battery level: %d | is charger connected: %d | is charging: %d \n", info.level, info.is_charger_connected, info.is_charging);
// Return the status of the initialization
return status;
}
void start_stream_ble(ba_eeg_manager** const manager, const int channels)
{
// Enable and set the gain for all electrode channels
for (int i = 0; i < channels; ++i)
{
ba_eeg_manager_set_channel_enabled(*manager, BA_EEG_CHANNEL_ID_ELECTRODE_CONTACT + i, true);
ba_eeg_manager_set_channel_enabled(*manager, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + i, true);
ba_eeg_manager_set_channel_gain(*manager, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + i, BA_GAIN_MODE_X8);
}
ba_eeg_manager_set_channel_enabled(*manager, BA_EEG_CHANNEL_ID_SAMPLE_NUMBER, true);
ba_eeg_manager_set_channel_enabled(*manager, BA_EEG_CHANNEL_ID_STREAMING, true);
// Set the impedance measurement mode to off
// Load the configuration
// ba_eeg_manager_load_config(*manager, NULL, NULL);
// Define the callback function for handling EEG data chunks
ba_callback_chunk my_callback = chunk_callback;
// Set the callback function for handling EEG data chunks
ba_eeg_manager_set_callback_chunk(*manager, my_callback, *manager);
// Start the EEG data streaming
// if (compatibility == BA_ERROR_OK)
// {
ba_eeg_manager_start_stream(*manager, NULL, NULL);
// }
printf("stream_start\n");
}
// Function to stop the Bluetooth EEG system and disconnect from the device
void disconnect_ble(ba_eeg_manager** const manager)
{
// Free the EEG manager instance
ba_eeg_manager_free(*manager);
}
// Main function to run the Bluetooth EEG system application
int main()
{
scan_devices();
printf("scanned....\n");
sleep_ms(5000);
// sleep(5);
manager1 = ba_eeg_manager_new();
uint8_t status = connect_ble(&manager1, DEVICE_NAME);
printf("is_conn: %d", ba_eeg_manager_is_connected(manager1));
// if (status != BA_ERROR_OK || compatibility == BA_ERROR_CONNECTION)
// {
// // sleep_ms(10000);
//
// printf("Error connecting to device: %d(%d)\n", status,
// compatibility); return status;
// }
// uint8_t ret =
// ba_eeg_manager_start_update(manager1, ota_update_callback, NULL);
// // Get the battery information
//
// printf("Update returned: %d", ret);
start_stream_ble(&manager1, CHANNELS_COUNT);
// Stop the EEG data streaming
for (int j = 0; j < 30; ++j)
{
uint8_t ret = ba_eeg_manager_annotate(manager1, "j");
printf("%d - returned: %d\n", j, ret);
sleep(1);
}
printf("annotations finished\n");
size_t annotation_size;
ba_annotation* annot;
int prev = 0;
ba_eeg_manager_get_annotations(manager1, &annot, &annotation_size);
printf("annotations: %zu\n", annotation_size);
for (size_t i = 0; i < annotation_size; i++)
{
printf("Annotation: %s (%zu) (%d)\n", annot[i].annotation, annot[i].timestamp, annot[i].timestamp - prev);
prev = annot[i].timestamp;
}
ba_eeg_manager_stop_stream(manager1, NULL, NULL);
printf("stream_stop\n");
ba_eeg_manager_disconnect(&manager1);
sleep_ms(4000);
disconnect_ble(&manager1);
sleep_ms(3000);
// Close the Bluetooth EEG system
ba_core_close();
return 0;
}