|
|
  |
быстрый алгоритм, определения отсуствующего байта произвольного массива байтов размером |
|
|
|
Jun 1 2007, 12:55
|

Местный
  
Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530

|
Цитата(GetSmart @ Jun 1 2007, 15:43)  Во время подготовки пакета к отправке из МК один раз в цикле проходите пакет и устанавливаете в 256-битном массиве (32-байтном) еденичный бит, соответствующий текущему байту в пакете. Пройдя весь пакет у вас будут установлены биты присутствующих байт. Далее первый не 0xff байт в этом массиве будет указывать на значение, которого нет в пакете. Это в принципе понятно, только он делав 256 байтный массив и дальше как вы пишите. Но для этого необходимо прокрутить три цикла, перевый для начального обнуления 256 байтного (битного) массива, второй для обозначения присутствующий символов, третий для поиска первого нулевого. Делать это в ПВЭМ и отправлять в МК можно, а вот крутить эти циклы в МК для обратной передачи пакетов может быть накладно. А вот если-бы существовал не слишком сложный алгоритм: в начале сброс какого-то значения (байта/слова), а дальше добавляется очередной байт и тут-же получаем значение байта, которого еще небыло.
--------------------
нельзя недооценивать предсказуемость глупости
|
|
|
|
|
Jun 1 2007, 13:25
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(GetSmart @ Jun 1 2007, 15:54)  И так до бесконечности... Выберите управляющий символ так, чтобы он не часто встречался в пакете. Да и размер пакета все-таки ограничен. Конечно есть мнение что Чак Норрис достчитал до бесконечности дважды! Но применительно к байтстаффинг протоколу - в худшем случае (если все байты данных в пакете будут равны управляющему символу, размер пакета увеличится всего лишь вдвое). Делать "strip" тобишь отцеплять лишние данные можно прямо в обработчике прерывания УАРТа нехитрой проверкой Код if ( (lastchar == CONTROL_CHAR) && (newchar == CONTROL_CHAR) ) return; добавлять избыточность, аналогично просто: Код for (i = 0; i < size; i++) { if (Packet[i] == CONTROL_CHAR) put_char( CONTROL_CHAR ); put_char(Packet[i]); }
|
|
|
|
|
Jun 1 2007, 14:58
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(GetSmart @ Jun 1 2007, 15:54)  И так до бесконечности... Не до бесконечности, а максимум в два раза. При всей на первый взгляд неприятности - используется массово. Смотрите PPP http://www.faqs.org/rfcs/rfc1171.html - там этих подставновок вообще немеряно, не только ограничитель пакета подставляется, а ещё куча байтов. И ничего. Цитата After FCS computation, the transmitter examines the entire frame between the two Flag Sequences. Each Flag Sequence, Control Escape octet and octet with value less than hexadecimal 0x20 is replaced by a two octet sequence consisting of the Control Escape octet and the original octet with bit 6 complemented (i.e., exclusive-or'd with hexadecimal 0x20). Я сам использую рамку SLIP http://www.faqs.org/rfcs/rfc1055.html - там подставляется два байта, ограничитель пакетов и тот, который используется как флаг подстановки. Работал лет 10 назад с каким-то радиомодемом, ему нужно было в этой рамке посылать пакеты, так и привык с тех пор :-) Очень удобно в WIN32 байт-ограничитель пакета задать как EVENT CHARACTER и буфер запросить гарантированно больше максимального пакета - и не дёргаться по каждому байту, а ждать только этого события и выгребать потом весь пакет. Кстати, вопрос к автору вопроса - а что будете делать, если вдруг все 256 байт будут разные, все байты есть во входном потоке? Возьмёте как флаговый произвольный? Ну так и делайте это сразу "без этих хлопот". Цитата(_artem_ @ Jun 1 2007, 17:36)  посмотрите в сторону битстаффинга. Пример - сигнализация MTP CCITT 7. Номер рекомендации не помню но можно и по поиску найти. Всё хорошо, максимальная растяжка пакета в худшей ситуации на 12.5%, а не вдвое, как у байт-стаффинга, но бит-стаффинг настолько муторно делать ручками до/после аппаратного UART, ориентированного на передачу байтов...
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jun 1 2007, 15:31
|
Местный
  
Группа: Свой
Сообщений: 316
Регистрация: 22-10-05
Пользователь №: 9 976

|
Полагаю, что для Вас в самый раз будет алгоритм byte stuffing'а Consistent Overhead Byte Stuffing. В этом алгоритме всегда добавляется только 1 байт при длине пакета не более 254 байт, еще плюс 1 байт - признак начала (или конца) пакета. Т.е. не нужно выделять память под буферы с большим запасом, расчитывая на наихудший случай. Реализация его тоже очень простая. Сам давно пользуюсь и доволен. Ссылка на описание: http://www.stuartcheshire.org/papers/COBSforToN.pdf
|
|
|
|
|
Jun 1 2007, 19:29
|

Местный
  
Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530

|
Цитата(defunct @ Jun 1 2007, 16:25)  Конечно есть мнение что Чак Норрис достчитал до бесконечности дважды! Ценю чувство юмора! А пока рассбираюсь с COBSforToN.pdf
Сообщение отредактировал sKWO - Jun 1 2007, 19:39
--------------------
нельзя недооценивать предсказуемость глупости
|
|
|
|
|
Jun 2 2007, 08:30
|

Местный
  
Группа: Свой
Сообщений: 345
Регистрация: 10-10-05
Пользователь №: 9 459

|
Цитата "Кривизна" протокола вносит ограничение на допустимые комбинации данных в пакете. То есть случайно попавшаяся 20-байтная (100-байтная) последовательность в пакете, совпадающая с синхронизацией введёт канал передачи в ступор. а про контрольную сумму забыли? чтоб еще и она совпала.:-) это уже слишком.:-)
--------------------
Если задачу можно решить, то не надо тревожиться. А если нельзя решить, то тревожиться бесполезно.
|
|
|
|
|
Jun 2 2007, 12:20
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(GetSmart @ Jun 2 2007, 13:04)  Да не забыл я про кс. Просто пакет со случайно оказавшейся в нем синхронизацией (хоть 20, хоть 100 байт) не сможет быть передан через канал как ни извращайся. КС позволит обнаружить то, что что-то передано неправильно и потребует повторить передачу этого пакета. Но и во второй раз передача накроется, и в третий. Содержимое же пакета нельзя заменить на другое. Оно как совпадало, так и будет совпадать с синхронизацией. Согласен, никто так не делает. Можно предложить расширенную версию байтстаффинга, ниже краткое описание того что должно быть: 1 - упр символ. 2 - символ старта пакета (распознается как старт только если идет после упр. символа) 3 - символ завершения пакета (распознается как конец пакета, только если идет после упр символа) 4 - два упр. символа подряд трактуются как символ данных равный упр. символу. 5 - одиночный упр. символ - не сопровождаемый ни старотовым символом, ни символом завершения - трактовать как сбой передачи - и прием пакета прекращать. 6 - CRC пакета очень желательно. Использую такой протокол для радио передачи - по вине протокола практически ничего не теряется и нет сбоев с определением начала/конца которые часто встречаются если использовать чистый байтстаффинг.
|
|
|
|
|
Jun 3 2007, 15:01
|
Участник

Группа: Свой
Сообщений: 69
Регистрация: 16-10-05
Пользователь №: 9 713

|
Цитата(sKWO @ Jun 1 2007, 15:30)  Товарищ это применил для передачи пакетов от ПЭВМ в МК. А вот для обратной передачи пришлось отказаться крутить циклы в МК. Для формирования пакетов 8-битных данных и передачи по RS232. Назначаю какой-то байт разделителем пакетов, например 0x55. Дальше необходимо присоеденить произвольный пакет размером <= 254 байт. Но в этом пакете могут быть байты 0x55. Поэтому их необходимо заменить каким-то другим байтом, которого в пакете точно нет. А раз размер пакета <= 254, то такой символ точно существует, например 0xAA. Результирующий пакет выглядит так: 0x55, 0xAA, а дальше весь исходный пакет с замененными значениями 0x55 на 0xAA. При приеме находим первый байт 0x55, запоминаем очередной байт 0xAA и дальше принимаем остальные данные заменяя встретившиеся байты равные запомненому (Для этого пакета 0xAA) на 0x55. Накладные расходы информативности канала на такую передачу не большие и можна нормально использовать RS232 для передачи проиозвольных 8-битных данных.
Что думаете по этому поводу? Спасибо. Используйте пакетную передачу данных. Например 1. Преамбула. 2. Преамбула2. 3. Код команды (или назначение пакета..., опционально). 4. Размер данных. 5. КС. (опция) 6. Данные. 7. CRC16 8. Признак конца пакета. Код 1 2 3 4 5 6 6 6 7 7 8 0x55 0xaa 0xXX 0x03 0x55 0xab 0xbc 0xcd crc0 crc1 0xfe Это всего лишь пример. У меня в проектах используется чуть более сложная структура (зато более гибкая), но Вы можете выбрать поля как Вы считаете нужным. Размер каждого поля тоже. Вот пример команды (вытянул из старого проекта) чтения системного времени устройства (МК шлет ответ ПК, в поле данных системное время, все hex): 55 AA 01 07 55 07 06 01 03 17 57 18 83 9A FE
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|