Skip to content

Commit 33dd321

Browse files
committed
Create explicit boards for Ganglion v2 and v3 firmwares
1 parent 56638e5 commit 33dd321

16 files changed

+508
-472
lines changed

src/board_controller/board_controller.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@
3838
#include "explore.h"
3939
#include "freeeeg.h"
4040
#include "galea.h"
41-
#include "ganglion.h"
42-
#include "ganglion_native.h"
41+
#include "ganglion_native_v2.h"
42+
#include "ganglion_native_v3.h"
43+
#include "ganglion_v2.h"
44+
#include "ganglion_v3.h"
4345
#include "ganglion_wifi.h"
4446
#include "gforce_dual.h"
4547
#include "gforce_pro.h"
@@ -106,7 +108,7 @@ int prepare_session (int board_id, const char *json_brainflow_input_params)
106108
board = std::shared_ptr<Board> (new Cyton (params));
107109
break;
108110
case BoardIds::GANGLION_BOARD:
109-
board = std::shared_ptr<Board> (new Ganglion (params));
111+
board = std::shared_ptr<Board> (new GanglionV3 (params));
110112
break;
111113
case BoardIds::CYTON_DAISY_BOARD:
112114
board = std::shared_ptr<Board> (new CytonDaisy (params));
@@ -250,7 +252,7 @@ int prepare_session (int board_id, const char *json_brainflow_input_params)
250252
board = std::shared_ptr<Board> (new Explore (board_id, params));
251253
break;
252254
case BoardIds::GANGLION_NATIVE_BOARD:
253-
board = std::shared_ptr<Board> (new GanglionNative (params));
255+
board = std::shared_ptr<Board> (new GanglionNativeV3 (params));
254256
break;
255257
case BoardIds::EMOTIBIT_BOARD:
256258
board = std::shared_ptr<Board> (new Emotibit (params));
@@ -299,6 +301,12 @@ int prepare_session (int board_id, const char *json_brainflow_input_params)
299301
case BoardIds::BIOLISTENER_BOARD:
300302
board = std::shared_ptr<Board> (new BioListener<8> (board_id, params));
301303
break;
304+
case BoardIds::GANGLION_V2_BOARD:
305+
board = std::shared_ptr<Board> (new GanglionV2 (params));
306+
break;
307+
case BoardIds::GANGLION_V2_NATIVE_BOARD:
308+
board = std::shared_ptr<Board> (new GanglionNativeV2 (params));
309+
break;
302310
default:
303311
return (int)BrainFlowExitCodes::UNSUPPORTED_BOARD_ERROR;
304312
}

src/board_controller/openbci/ganglion.cpp

Lines changed: 5 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
int Ganglion::num_objects = 0;
1818

1919

20-
Ganglion::Ganglion (struct BrainFlowInputParams params)
21-
: Board ((int)BoardIds::GANGLION_BOARD, params)
20+
Ganglion::Ganglion (BoardIds board_id, struct BrainFlowInputParams params)
21+
: Board ((int)board_id, params)
2222
{
2323
Ganglion::num_objects++;
2424
if (Ganglion::num_objects > 1)
@@ -30,7 +30,6 @@ Ganglion::Ganglion (struct BrainFlowInputParams params)
3030
is_valid = true;
3131
}
3232
use_mac_addr = (params.mac_address.empty ()) ? false : true;
33-
firmware = 0;
3433
is_streaming = false;
3534
keep_alive = false;
3635
initialized = false;
@@ -268,14 +267,7 @@ void Ganglion::read_thread ()
268267

269268
if (data.data[0] <= 200)
270269
{
271-
if (firmware == 3)
272-
{
273-
decompress_firmware_3 (&data, last_data, acceleration, package);
274-
}
275-
else if (firmware == 2)
276-
{
277-
decompress_firmware_2 (&data, last_data, acceleration, package);
278-
}
270+
decompress (&data, last_data, acceleration, package);
279271
}
280272
else if ((data.data[0] > 200) && (data.data[0] < 206))
281273
{
@@ -371,195 +363,8 @@ void Ganglion::read_thread ()
371363
delete[] package;
372364
}
373365

374-
void Ganglion::decompress_firmware_3 (
375-
struct GanglionLib::GanglionData *data, float *last_data, double *acceleration, double *package)
376-
{
377-
int bits_per_num = 0;
378-
unsigned char package_bits[160] = {0}; // 20 * 8
379-
for (int i = 0; i < 20; i++)
380-
{
381-
uchar_to_bits (data->data[i], package_bits + i * 8);
382-
}
383-
384-
// 18 bit compression, sends 17 MSBs + sign bit of 24-bit sample
385-
if (data->data[0] >= 0 && data->data[0] < 100)
386-
{
387-
int last_digit = data->data[0] % 10;
388-
switch (last_digit)
389-
{
390-
// accel data is signed, so we must cast it to signed char
391-
// swap x and z, and invert z to convert to standard coordinate space.
392-
case 0:
393-
acceleration[2] = -accel_scale * (char)data->data[19];
394-
break;
395-
case 1:
396-
acceleration[1] = accel_scale * (char)data->data[19];
397-
break;
398-
case 2:
399-
acceleration[0] = accel_scale * (char)data->data[19];
400-
break;
401-
default:
402-
break;
403-
}
404-
bits_per_num = 18;
405-
}
406-
else if (data->data[0] >= 100 && data->data[0] < 200)
407-
{
408-
bits_per_num = 19;
409-
}
410-
411-
// handle compressed data for 18 or 19 bits
412-
for (int i = 8, counter = 0; i < bits_per_num * 8; i += bits_per_num, counter++)
413-
{
414-
if (bits_per_num == 18)
415-
{
416-
last_data[counter] = (float)(cast_ganglion_bits_to_int32<18> (package_bits + i) << 6);
417-
}
418-
else
419-
{
420-
last_data[counter] = (float)(cast_ganglion_bits_to_int32<19> (package_bits + i) << 5);
421-
}
422-
}
423-
424-
// add first encoded package
425-
package[board_descr["default"]["package_num_channel"].get<int> ()] = data->data[0];
426-
package[board_descr["default"]["eeg_channels"][0].get<int> ()] = eeg_scale * last_data[0];
427-
package[board_descr["default"]["eeg_channels"][1].get<int> ()] = eeg_scale * last_data[1];
428-
package[board_descr["default"]["eeg_channels"][2].get<int> ()] = eeg_scale * last_data[2];
429-
package[board_descr["default"]["eeg_channels"][3].get<int> ()] = eeg_scale * last_data[3];
430-
package[board_descr["default"]["accel_channels"][0].get<int> ()] = acceleration[0];
431-
package[board_descr["default"]["accel_channels"][1].get<int> ()] = acceleration[1];
432-
package[board_descr["default"]["accel_channels"][2].get<int> ()] = acceleration[2];
433-
package[board_descr["default"]["timestamp_channel"].get<int> ()] = data->timestamp;
434-
push_package (package);
435-
// add second package
436-
package[board_descr["default"]["eeg_channels"][0].get<int> ()] = eeg_scale * last_data[4];
437-
package[board_descr["default"]["eeg_channels"][1].get<int> ()] = eeg_scale * last_data[5];
438-
package[board_descr["default"]["eeg_channels"][2].get<int> ()] = eeg_scale * last_data[6];
439-
package[board_descr["default"]["eeg_channels"][3].get<int> ()] = eeg_scale * last_data[7];
440-
package[board_descr["default"]["timestamp_channel"].get<int> ()] = data->timestamp;
441-
push_package (package);
442-
}
443-
444-
void Ganglion::decompress_firmware_2 (
445-
struct GanglionLib::GanglionData *data, float *last_data, double *acceleration, double *package)
446-
{
447-
int bits_per_num = 0;
448-
unsigned char package_bits[160] = {0}; // 20 * 8
449-
for (int i = 0; i < 20; i++)
450-
{
451-
uchar_to_bits (data->data[i], package_bits + i * 8);
452-
}
453-
454-
float delta[8] = {0.f}; // delta holds 8 nums (4 by each package)
455-
456-
// no compression, used to init variable
457-
if (data->data[0] == 0)
458-
{
459-
// shift the last data packet to make room for a newer one
460-
last_data[0] = last_data[4];
461-
last_data[1] = last_data[5];
462-
last_data[2] = last_data[6];
463-
last_data[3] = last_data[7];
464-
465-
// add new packet
466-
last_data[4] = (float)cast_24bit_to_int32 (data->data + 1);
467-
last_data[5] = (float)cast_24bit_to_int32 (data->data + 4);
468-
last_data[6] = (float)cast_24bit_to_int32 (data->data + 7);
469-
last_data[7] = (float)cast_24bit_to_int32 (data->data + 10);
470-
471-
// scale new packet and insert into result
472-
package[board_descr["default"]["package_num_channel"].get<int> ()] = 0.;
473-
package[board_descr["default"]["eeg_channels"][0].get<int> ()] = eeg_scale * last_data[4];
474-
package[board_descr["default"]["eeg_channels"][1].get<int> ()] = eeg_scale * last_data[5];
475-
package[board_descr["default"]["eeg_channels"][2].get<int> ()] = eeg_scale * last_data[6];
476-
package[board_descr["default"]["eeg_channels"][3].get<int> ()] = eeg_scale * last_data[7];
477-
package[board_descr["default"]["accel_channels"][0].get<int> ()] = acceleration[0];
478-
package[board_descr["default"]["accel_channels"][1].get<int> ()] = acceleration[1];
479-
package[board_descr["default"]["accel_channels"][2].get<int> ()] = acceleration[2];
480-
package[board_descr["default"]["timestamp_channel"].get<int> ()] = data->timestamp;
481-
push_package (package);
482-
return;
483-
}
484-
// 18 bit compression, sends delta from previous value instead of real value!
485-
else if (data->data[0] >= 1 && data->data[0] <= 100)
486-
{
487-
int last_digit = data->data[0] % 10;
488-
switch (last_digit)
489-
{
490-
// accel data is signed, so we must cast it to signed char
491-
// swap x and z, and invert z to convert to standard coordinate space.
492-
case 0:
493-
acceleration[2] = -accel_scale * (char)data->data[19];
494-
break;
495-
case 1:
496-
acceleration[1] = accel_scale * (char)data->data[19];
497-
break;
498-
case 2:
499-
acceleration[0] = accel_scale * (char)data->data[19];
500-
break;
501-
default:
502-
break;
503-
}
504-
bits_per_num = 18;
505-
}
506-
else if (data->data[0] >= 101 && data->data[0] <= 200)
507-
{
508-
bits_per_num = 19;
509-
}
510-
511-
// handle compressed data for 18 or 19 bits
512-
for (int i = 8, counter = 0; i < bits_per_num * 8; i += bits_per_num, counter++)
513-
{
514-
if (bits_per_num == 18)
515-
{
516-
delta[counter] = (float)cast_ganglion_bits_to_int32<18> (package_bits + i);
517-
}
518-
else
519-
{
520-
delta[counter] = (float)cast_ganglion_bits_to_int32<19> (package_bits + i);
521-
}
522-
}
523-
524-
// apply the first delta to the last data we got in the previous iteration
525-
for (int i = 0; i < 4; i++)
526-
{
527-
last_data[i] = last_data[i + 4] - delta[i];
528-
}
529-
530-
// apply the second delta to the previous packet which we just decompressed above
531-
for (int i = 4; i < 8; i++)
532-
{
533-
last_data[i] = last_data[i - 4] - delta[i];
534-
}
535-
536-
// add first encoded package
537-
package[board_descr["default"]["package_num_channel"].get<int> ()] = data->data[0];
538-
package[board_descr["default"]["eeg_channels"][0].get<int> ()] = eeg_scale * last_data[0];
539-
package[board_descr["default"]["eeg_channels"][1].get<int> ()] = eeg_scale * last_data[1];
540-
package[board_descr["default"]["eeg_channels"][2].get<int> ()] = eeg_scale * last_data[2];
541-
package[board_descr["default"]["eeg_channels"][3].get<int> ()] = eeg_scale * last_data[3];
542-
package[board_descr["default"]["accel_channels"][0].get<int> ()] = acceleration[0];
543-
package[board_descr["default"]["accel_channels"][1].get<int> ()] = acceleration[1];
544-
package[board_descr["default"]["accel_channels"][2].get<int> ()] = acceleration[2];
545-
package[board_descr["default"]["timestamp_channel"].get<int> ()] = data->timestamp;
546-
push_package (package);
547-
// add second package
548-
package[board_descr["default"]["eeg_channels"][0].get<int> ()] = eeg_scale * last_data[4];
549-
package[board_descr["default"]["eeg_channels"][1].get<int> ()] = eeg_scale * last_data[5];
550-
package[board_descr["default"]["eeg_channels"][2].get<int> ()] = eeg_scale * last_data[6];
551-
package[board_descr["default"]["eeg_channels"][3].get<int> ()] = eeg_scale * last_data[7];
552-
package[board_descr["default"]["timestamp_channel"].get<int> ()] = data->timestamp;
553-
push_package (package);
554-
}
555-
556366
int Ganglion::config_board (std::string config, std::string &response)
557367
{
558-
if (config == "get_firmware_version")
559-
{
560-
response = std::to_string (firmware);
561-
return (int)BrainFlowExitCodes::STATUS_OK;
562-
}
563368
const char *conf = config.c_str ();
564369
safe_logger (spdlog::level::debug, "Trying to config Ganglion with {}", conf);
565370
// need to pause, config and restart. I have no idea why it doesnt work if I restart it inside
@@ -674,17 +479,12 @@ int Ganglion::call_open ()
674479

675480
GanglionLib::ConnectionParameters connection_params;
676481
connection_params.mac_address = const_cast<char *> (params.mac_address.c_str ());
677-
connection_params.firmware = 2;
678482

679483
res = func ((void *)&connection_params);
680-
681-
safe_logger (
682-
spdlog::level::info, "detected firmware version {}", connection_params.firmware);
683-
firmware = connection_params.firmware;
684484
}
685485
else
686486
{
687-
int (*func) (void *) = (int (*) (void *))dll_loader->get_address ("open_ganglion");
487+
int (*func) () = (int (*) ())dll_loader->get_address ("open_ganglion");
688488
if (func == NULL)
689489
{
690490
safe_logger (spdlog::level::err, "failed to get function address for open_ganglion");
@@ -694,9 +494,7 @@ int Ganglion::call_open ()
694494
safe_logger (
695495
spdlog::level::info, "mac address is not specified, try to find ganglion without it");
696496

697-
res = func ((void *)&firmware);
698-
699-
safe_logger (spdlog::level::info, "detected firmware version {}", firmware);
497+
res = func ();
700498
}
701499
if (res != GanglionLib::CustomExitCodes::STATUS_OK)
702500
{

src/board_controller/openbci/ganglion_bglib/inc/ganglion_types.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,5 @@ namespace GanglionLib
9191
struct ConnectionParameters
9292
{
9393
char *mac_address;
94-
uint8_t firmware;
9594
};
9695
}

src/board_controller/openbci/ganglion_bglib/main.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ namespace GanglionLib
2424
std::deque<struct GanglionLib::GanglionData> data_queue;
2525
SpinLock lock;
2626
volatile bd_addr connect_addr;
27-
volatile uint8 firmware = 0;
2827
volatile uint8 connection = -1;
2928
volatile uint16 ganglion_handle_start = 0;
3029
volatile uint16 ganglion_handle_end = 0;
@@ -64,7 +63,7 @@ namespace GanglionLib
6463
return (int)CustomExitCodes::STATUS_OK;
6564
}
6665

67-
int open_ganglion (void *param)
66+
int open_ganglion ()
6867
{
6968
if (uart_open (uart_port))
7069
{
@@ -88,9 +87,6 @@ namespace GanglionLib
8887

8988
int result = open_ble_dev ();
9089

91-
uint8_t *firmware_ptr = (uint8_t *)param;
92-
*firmware_ptr = firmware;
93-
9490
return result;
9591
}
9692

@@ -140,7 +136,6 @@ namespace GanglionLib
140136
ble_cmd_gap_end_procedure ();
141137

142138
int result = open_ble_dev ();
143-
connection_parameters->firmware = firmware;
144139
return result;
145140
}
146141

0 commit comments

Comments
 (0)