всех 4-х каналов последовательнои входа REF в конце каждой серии, пока не получит команду “Z”. Эти значения “Packet ID” перечислены в таблице ниже. Данные импеданса отправляются в виде строки ASCII, представляющей измеренное значение в омах (табл. 4.2).
|
|
|
Таблица 4.2 |
|
|
Значения поля Packet ID |
|||
Десятичный |
Байт ID |
Тип |
|
|
идентификатор байта |
HEX |
данных |
Описание |
|
|
|
|
|
|
0 |
00 |
24bit |
Данные без сжатия |
|
|
|
|
|
|
1-100 |
0x01-0x64 |
18bit |
18-битное сжатие с акселерометром |
|
|
|
|
|
|
|
|
|
19-битное сжатие без |
|
101-200 |
0x65-0xC8 |
19bit |
акселерометра |
|
|
|
|
|
|
201 |
0xC9 |
impedance |
Канал импеданса 1 |
|
|
|
|
|
|
202 |
0xCA |
impedance |
Канал импеданса 2 |
|
|
|
|
|
|
203 |
0xCB |
impedance |
Канал Импеданса 3 |
|
|
|
|
|
|
204 |
0xCC |
impedance |
Канал импеданса 4 |
|
|
|
|
|
|
205 |
0xCD |
impedance |
Ссылка на канал импеданса |
|
|
|
|
|
|
206 |
0xCE |
multi |
Часть сообщения ASCII |
|
|
|
|
|
|
207 |
0xCF |
multiStop |
Конец сообщения ASCII |
|
|
|
|
|
|
4.6.7. Вывод протокола
Плата Ganglion иногда отправляет подробные данные через соединение BLE. В этом случае Ganglion может отправлять от 1 до многих пакетов подробных данных в формате ASCII. “Packet ID” для ASCII сообщений проинформирует компьютер, если сообщение не будет сделано и он должен ожидать другой пакет “206” или “0xCE”. Когда Ganglion отправляет последний пакет сообщений ASCII, то “Packet ID” будет иметь значение “207” или “0xCF”.
100
4.6.8. Примеры интерпретации данных с платы Ganglion
При передаче 24-х битных необработанных данных без сжатия они всегда сохраняются, если приходит “Byte ID” равный “0”.
4.6.8.1. 18-битное дельта-сжатие
Далее рассмотрим практический пример передачи 18-битных данных на основе автоматизированного теста, используемого в драйвере Ganglion NodeJS, для объяснения стратегии 18-ти разрядного дельта-сжатия.
let buffer = new Buffer(
[
0b00000001, // 0 0b00000000, // 1 0b00000000, // 2 0b00000000, // 3 0b00000000, // 4 0b00100000, // 5 0b00000000, // 6 0b00101000, // 7 0b00000000, // 8 0b00000100, // 9 0b10000000, // 10 0b00000000, // 11 0b10111100, // 12 0b00000000, // 13 0b00000111, // 14 0b00000000, // 15 0b00101000, // 16 0b11000000, // 17 0b00001010, // 18 0b00001110 // 19 ]);
let expectedValue = [[0, 2, 10, 4], [131074, 245760, 114698, 49162]];
Первый сжатый канал в первой выборке будет получен из первых двух байтов плюс первые два бита третьего байта: канал 1 - выборка 1 - “0b000000000000000000” или “0” в десятичном формате.
Второй сжатый канал в первой выборке будет получен из последних шести битов третьего байта, всех четырех байтов и первых четырех битов пятого байта: канал 2 - выборка 1 “0b000000000000000010” или “2” в
десятичном формате.
Третья сжатая выборка во второй выборке будет получена из последних четырех битов 14-го байта, всех битов 15-го байта и первых шести битов 16-го байта: канал 3 - выборка 2 “0b011100000000001010” или “114698” в десятичном виде.
Чтобы получить данные 8-битного акселерометра с частотой 10 Гц из 18битных пакетов, необходимо задать модуль 10-байтового идентификатора “Byte
101
ID”: если (идентификатор байта “% 10”) равен 1, 2 и 3, то необходимо брать последний байт, чтобы получить значения X, Y и Z.
В вышеприведенном примере байт 19 - это последний байт, он имеет значение 14, или “0x0E”, которое будет сохранено как значение оси X для этого образца акселерометра.
Номер образца для образца 1 будет “1” и номер образца для образца 2 будет “2”. Если идентификатор байта был 47, а номер образца был “1”, то получим номер 93, а номер образца 2 - 94.
Далее рассмотрим отрицательные значения.
let buffer = new Buffer(
[
0b00000001, // 0 0b11111111, // 1 0b11111111, // 2 0b01111111, // 3 0b11111111, // 4 0b10111111, // 5 0b11111111, // 6 0b11100111, // 7 0b11111111, // 8 0b11110101, // 9 0b00000000, // 10 0b00000001, // 11 0b01001111, // 12 0b10001110, // 13 0b00110000, // 14 0b00000000, // 15 0b00011111, // 16 0b11110000, // 17 0b00000001 // 18 ]);
let expectedValue = [[-3, -5, -7, -11], [-262139, -198429, -262137, -4095]];
Первый сжатый канал в первой выборке будет получен из первых двух байтов плюс первые два бита третьего байта для образования общего количества 19 бит: канал 1 - выборка 1 – “0b111111111111111101” – или “3” в
десятичном формате.
Второй сжатый канал в выборке два будет получен из последних шести битов 12-го байта, целого байта 13 и первых четырех битов из байта 14: канал 2 - выборка 2 – “0b001111100011100011” или “198429” в десятичном формате. “MSB” будет иметь значение “0”, но это будет отрицательное число, потому что значение “LSB” будет “1”.
4.6.8.2. 19-битное дельта-сжатие
Для объяснения стратегии 19-разрядного дельта-сжатия рассмотрим практический пример на основе автоматизированного теста, используемого в драйвере Ganglion NodeJS.
102
let buffer = new Buffer(
[
0b01100101, // 0 0b00000000, // 1 0b00000000, // 2 0b00000000, // 3 0b00000000, // 4 0b00001000, // 5 0b00000000, // 6 0b00000101, // 7 0b00000000, // 8 0b00000000, // 9 0b01001000, // 10 0b00000000, // 11 0b00001001, // 12 0b11110000, // 13 0b00000001, // 14 0b10110000, // 15 0b00000000, // 16 0b00110000, // 17 0b00000000, // 18 0b00001000 // 19 ]);
let expectedValue = [[0, 2, 10, 4], [262148, 507910, 393222, 8]];
Первый сжатый канал в первой выборке будет получен из первых двух байтов плюс первые три бита третьего байта для получения общего количества 19 битов: канал 1 - выборка 1 – “0b0000000000000000000” или “0” в десятичном формате.
Второй сжатый канал во второй выборке будет получен из последнего бита в байте №12, всех байтов №13 и №14 и только первых двух битов байта №15: канал 2 - выборка 2 – “0b1111100000000000110” или “507910” в десятичном формате. “MSB” будет иметь значение “1”, но это положительное число, потому что “LSB” будет иметь значение “0”.
Номер образца для образца 1 равен “1” и номер образца для образца 2 будет “2”. Если идентификатор байта был “104”, то номер выборки 1 будет “7а”, а номер выборки 2 будет “8”.
Далее рассмотрим отрицательные значения.
let buffer = new Buffer(
[
0b01100101, // 0 0b11111111, // 1 0b11111111, // 2 0b10111111, // 3 0b11111111, // 4 0b11101111, // 5 0b11111111, // 6 0b11111100, // 7 0b11111111, // 8 0b11111111, // 9 0b01011000, // 10 0b00000000, // 11 0b00001011, // 12 0b00111110, // 13
103
0b00111000, // 14 0b11100000, // 15 0b00000000, // 16 0b00111111, // 17 0b11110000, // 18 0b00000001 // 19 ]);
let expectedValue = [[-3, -5, -7, -11], [-262139, -198429, -262137, -4095]];
Обращение к LSB происходит для 19-битного числа. Первый сжатый канал в выборке №1 будет получен из первых двух байтов плюс первые три бита третьего байта: канал 1 - выборка 1 “0b1111111111111111101” или “3” в десятичном формате.
Четвертый сжатый канал в выборке №2 будет получен из последних трех битов байта №17 и всех байтов №18 и №19: канал 4 - выборка 2 “0b001111100011100011” или “198429” в десятичном формате. “MSB” будет иметь значение “0”, но это отрицательное число, так как “LSB” будет иметь значение “1”.
Значения импеданса отправляются с байтовыми идентификаторами в формате ASCII, заканчивающемся на “Z”. Разбор необходимо проводить от байта №1, пока не встретится “Z”.
4.6.8.3. 18-битные данные со знаком
Сжатые значения регистрируемых данных ЭЭГ передаются в виде 18разрядного целого числа со знаком, что немного необычно. Но используется этот числовой формат потому, что это родной формат, используемый A/D- чипом, который является основным на плате Ganglion. Чтобы преобразовать этот необычный числовой формат в более стандартное 32-разрядное целое число со знаком, можно взять некоторые идеи из примера кода NodeJS (он же JavaScript):
/**
*Converts a special ganglion 18 bit compressed number
*The compressions uses the LSB, bit 1, as the signed bit, instead of using
*the MSB. Therefore you must not look to the MSB for a sign extension, one
*must look to the LSB, and the same rules applies, if it's a 1, then it's a
*negative and if it's 0 then it's a positive number.
*@param threeByteBuffer {Buffer}
*A 3-byte buffer with only 18 bits of actual data.
*@return {number} A signed integer.
*/
function convert18bitAsInt32 (threeByteBuffer) { let prefix = 0;
if (threeByteBuffer[2] & 0x01 > 0) { // console.log('\t\tNegative number') prefix = 0b11111111111111;
}
return (prefix << 18) | (threeByteBuffer[0] << 16) | (threeByteBuffer[1] << 8) | threeByteBuffer[2];
}
104