В этой статье, мы попытаемся разобраться в логике работы блока Packet Encoder
Данный блок обычно применяется в различных схемах передачи данных.
Итак, приступим.
Для начала создадим следующий простой граф:
Настроим все входы и выходы блоков использовать тип Byte, и создадим простой текстовый файл ascii_data.txt co следующим простым содержимым:
abcdefghijk1234567890
Этот файл мы будем использовать в качестве источника данных в File Source. В блоке File Sink задайте имя выходному файлу packed_data.bin
Итак, мы все настроили, запускаем граф на исполнение. Ждем немного, и останавливаем выполнение.
Теперь давайте изучим содержимое получившегося запакованного файла. Открываем терминал, и перемещаемся в каталог с нашим исходным файлом, и запакованым для дальнейшей передачи. Воспользуемся Unix командой hexdump с ключом «-C» для того чтобы отобразить содержимое в удобном для анализа виде.
Мда, с первого взгляда все очень загадочно. Нигде не проглядывается последовательностей исходного файла. Но на то кодировщик и пакетный, что бы кодировать пакетами с регулярной структрой.
Взглянем еще раз повнимательнее. Похоже на то, что последовательность байтов a4 f2 ac dd a4 e2 f2 8c 20 fc 00 09 00 09 повторяется несколько раз. Но что это?
Настало время нырнуть в глубину GnuRadio, и поглядеть что делает наш блок.
Скачаем исходный код Gnuradio, и откроем файл gnuradio/gr-digital/python/digital/packet_utils.py. Все самое интересное происходит в функции make_packet
def make_packet(payload, samples_per_symbol, bits_per_symbol, preamble=default_preamble, access_code=default_access_code, pad_for_usrp=True, whitener_offset=0, whitening=True, calc_crc=True):
Функиця принимает в качестве параметров блок из байт для передачи, число семплов на один символ, кол-во бит на символ, преамбулу, код доступа, булево значение для указания генерации отметок для USRP, сдвиг для отбеливателя, включать ли отбеливатель, и генерировать ли CRC.
if not is_1_0_string(preamble): raise ValueError, "preamble must be a string containing only 0's and 1's (%r)" % (preamble,) if not is_1_0_string(access_code): raise ValueError, "access_code must be a string containing only 0's and 1's (%r)" % (access_code,) if not whitener_offset >=0 and whitener_offset < 16: raise ValueError, "whitener_offset must be between 0 and 15, inclusive (%i)" % (whitener_offset,)
Далее в трех условиях проверяется состоит ли код доступа и преамбула из одних только единиц и нулей, и не превышает ли сдвиг отдбеливателя 15.
if(calc_crc): payload_with_crc = crc.gen_and_append_crc32(payload) else: payload_with_crc = payload
Ага, если включен подсчет CRC (а у нас он включен), то берем 5 наших байт вычисляем для них CRC и добавляем к данным. Попробуем это записать
61 62 63 64 65 + 6F 5B 4D F4
L = len(payload_with_crc) MAXLEN = len(random_mask_tuple) if L > MAXLEN: raise ValueError, "len(payload) must be in [0, %d]" % (MAXLEN,)
Определяем длину нашего блока данных (данные + CRC32), и сравниваем его длинну с длиной переменной random_mask_tuple в которой хранится большая битовая маска. Если вы прокрутите вниз, к самому концу файла, то вы увидите ее содержание, и пояснение, что эти значения в маске являются выводом 15 битного LSFR.
if whitening: pkt = ''.join((packed_preamble, packed_access_code, make_header(L, whitener_offset), whiten(payload_with_crc, whitener_offset), '\x55')) else: pkt = ''.join((packed_preamble, packed_access_code, make_header(L, whitener_offset), (payload_with_crc), '\x55')) if pad_for_usrp: pkt = pkt + (_npadding_bytes(len(pkt), int(samples_per_symbol), bits_per_symbol) * '\x55') return pkt
Вот мы и добрались до сути.
В случае если включено отбеливание (а оно у нас включено) то происходит следующее:
Берем и ставим в начало преамбулу. Если она не задана, то используется предопределенное значение A4 F2.
A4 F2
Далее к преамбуле добавляем код доступа, котороый тоже если не задан, будет использован предопределенным значением AC DD A4 E2 F2 8C 20 FC
A4 F2 AC DD A4 E2 F2 8C 20 FC
Добавляем заголовок в кототором указана длина нашего пактета данных (вместе с CRC32), и смещение для отбеливания. 00 09 00 09
A4 F2 AC DD A4 E2 F2 8C 20 FC 00 09 00 09
Потом мы выполняем отбеливание. Отбеливанием тут является побайтовая операция XOR над блоком данных с CRC и равной ему по длине байтовой последовательности из random_mask_tuple (в переменной значения представлены в десятичном виде, я перевел их для удобства в шестнадцатеричную форму)
61 62 63 64 65 6F 5B 4D F4 ^ FF 3F 00 10 00 0C 00 05 C0
————————————————————————————
9E 5D 63 74 65 af 5b 48 34
И вот мы объединяем все вместе:
A4 F2 AC DD A4 E2 F2 8C 20 FC 00 09 00 09 9E 5D 63 74 65 af 5b 48 34
Ну вот. Мы получили точно такой же пакет как в сегенерированном файле.
Теперь для вас не будет загадкой работа данного блока.