riupipi.text -*- Text -*- Управление контроллером Fourbit SPI Иван Шмаков 2019-06-20 Я, владелец авторских прав на это произведение, передаю его в общественное достояние. Это разрешение действует по всему миру. В некоторых странах это не может быть возможно юридически, в таком случае: Я даю право кому угодно использовать данное произведение в любых целях и без каких-либо условий, за исключением таких условий, которых требует закон. (Исходно опубликовано: http://transfer.sh/ /riupipi.text.) Краткая справка Контроллер Fourbit SPI в текущей редакции принимает команды по шине SPI (как ведомое устройство; «режим 0» контроллера AVR) и управляет семью цифровыми линиями, включая: • «готовность» — управляет одноименным светодиодным индикатором (свечение — контроллер готов к приему команд; мерцание — контроллер успешно принимает октеты по шине SPI); • DO0, …, DO3 — основные сигналы; • EO0, EO1 — вспомогательные сигналы, связанные по определенному закону с DO0, DO1. Шина SPI представлена сигналами тактирования (SCK), ввода-вывода (MISO, MOSI) и сигналом выбора устройства (/CS; активный уровень — низкий.) ** На разъем управления целевого устройства выведены линии /CS0, …, /CS3. Одна (и только одна!) из этих линий соединена с линией /CS контроллера перемычкой, устанавливаемой на этапе сборки, что позволяет подключить до четырех устройств к одной шине. Ведущее устройство передает контроллеру октет команды, четыре старших бита которого задают желаемое состояние основных линий (DO0, …, DO3; DO3 — старший бит октета), четыре младших используются как биты четности кода Хэмминга (8, 4). В ответ контроллер возвращает таким же образом кодированное состояние на момент начала (!) обмена. Пример 1: команда ответ комментарий 0x87 0x00 начальное состояние - 0000₂; 0x87 0x87 после переключения; 0x87 0x87 0x5a 0x87 0x5a 0x87 двойная ошибка — команда отклонена. 0x00 0x87 0x00 0x00 Для изменении состояния рекомендуется выполнять повторную передачу команды до получения ответа с желаемым состоянием, выдерживая интервал между пересылками не менее 10 мкс, в течение которого линия /CS должна быть неактивна (т. е., в состоянии высокого уровня.) ** В зависимости от устройства, некоторые комбинации сигналов DO0, …, DO3 могут быть запретными; содержащие (после, возможно, коррекции одиночной ошибки) их команды будут отклонены — как если бы была обнаружена двойная ошибка. Так, например, в отсутствие многоканального коммутатора, допустимы лишь команды, переключающие реле — младший бит DO0. С другой стороны, в устройствах, содержащих шестиканальный коммутатор, допустимы значения DO1, …, DO3 лишь в диапазоне 0 до 5 включительно. ** На физические линии, которые должны всегда находится в состоянии низкого уровня, при испытаниях устройства могут быть установлены светодиоды красного цвета свечения. На используемых линиях DO0, …, DO3 устанавливаются светодиоды оранжевого цвета. Для индикации состояния EO0 — желтого или белого при синфазном управлении, или синего в противном случае. !! Для гарантированного срабатывания реле обновление бита DO0 состояния выполняется с задержкой (10 ÷ 20) мс. Пример 2: команда ответ комментарий 0x87 0x00 начальное состояние - 0000₂; 0x87 0x00 состояние 1000₂ не действительно — в устройстве отсутствует многоканальный коммутатор; 0x1e 0x00 0x1e 0x00 задержка переключения (10 ÷ 20) мс; 0x1e 0x1e переключение завершено. Таблица действительных кодов В данном устройстве релизовано кодирование согласно следующей таблице. Действительны кроме того все коды, отличающиеся от указанных значением ровно одного бита («одиночная ошибка.») DO3 DO2 DO1 DO0 код 0 0 0 0 00000000 0 0 0 1 00011110 0 0 1 0 00101101 0 0 1 1 00110011 0 1 0 0 01001011 0 1 0 1 01010101 0 1 1 0 01100110 0 1 1 1 01111000 1 0 0 0 10000111 1 0 0 1 10011001 1 0 1 0 10101010 1 0 1 1 10110100 1 1 0 0 11001100 1 1 0 1 11010010 1 1 1 0 11100001 1 1 1 1 11111111 Использованные реализации кодирования Хэмминга (8, 4) /*** hamming84.c -*- C -*- */ /** Hamming[8, 4] coding */ /*** Ivan Shmakov, 2019 */ /*** Code */ #include #include static const uint8_t syncor[8] = { 1, 2, 4, 128, 8, 64, 32, 16 }; static int_least8_t parity (uint_least8_t value) { int_least8_t r; for (r = 0; value > 0; r ^= (1 & value), value >>= 1) ; /* . */ return r; } uint_least8_t hamming84_encode_hi (uint_least8_t value) { const uint_least8_t m = 0160; uint_least8_t r; int_least8_t i; for (i = 4, r = (value & 017), r |= (r << 4); i > 0; --i) { int_least8_t q = parity ((r & m) >> 4); r <<= 1; r |= q; } /* . */ return (r & 0377); } int_least16_t hamming84_decode_hi (uint_least8_t value) { uint_least8_t m, q; for (m = 0170, value &= 0377, q = parity (value); (m & 016) != 0; (m >>= 1), (m &= (~ 010)), (m |= 0200)) { q <<= 1; q |= parity ((m & value)); } return ((q == 0) ? (value >> 4) : (q & 010) ? ((value ^ syncor[q & 7]) >> 4) : - value); } /*** hamming84.c ends here */ ### hamming84.perl -*- Perl -*- ## Hamming[8, 4] coding ### Ivan Shmakov, 2019 ### Code use common::sense; sub parity { my ($v) = @_; my $r = 0; while ($v > 0) { $r ^= (1 & (($v >> 1) ^ $v)); $v >>= 2; } ## . $r; } sub hamming84_encode { my $r = (017 & $_[0]); $r |= ($r << 4); my $m = 0160; foreach my $i (0 .. 3) { my $q = (($r & $m) >> 4); $r <<= 1; $r &= 0377; $r |= (1 & ($q ^ ($q >> 1) ^ ($q >> 2) ^ ($q >> 3))); }; ## . $r; } sub hamming84_decode { my ($v) = @_; my @cor = qw (1 2 4 128 8 64 32 16); my $par = parity ($v); for (my $m = 0170; ($m & 016) != 0; ($m >>= 1), ($m &= (~ 010)), ($m |= 0200)) { $par <<= 1; $par |= parity ($m & $v); }; warn ("N: Hamming[8, 4] p-value: ", $par, "\n") unless ($par == 0); ## . ($par == 0 ? $v : ($v ^ $cor[($par & 7)])); } ### hamming84.perl ends here riupipi.text закончился здесь