Очень неохота было к этой теме приступать. С одной стороны, "дело техники" - одно дело убедиться, что достигаются заявленные точности, и в принципе продемонстрировать, как все 6 параметров измеряются, и совсем другое - организовать штатный обмен через наш любимый ГОСТ Р 52070-2003, который Mil-Std1553B.
С другой, как-то оно уродски получалось. Не люблю большие таблицы, или особо отожранную комбинаторную логику, когда нужно сделать 4-5 выходов, зависящих от десятка входов. Перфекционизм требует сделать всё изящно, а оно, зараза, не выходит!
Но надо уже завершить, это сейчас самый главный мой "должок".
И вот вчера, наконец, оно заработало!
Напомню, в чём сыр-бор. К нам приходят командные слова с разными подадресами. Изначально подадресов 32, причём 0 и 31 соответствуют командам управления, определённым в ГОСТе. Часть из них мы используем: Синхронизация (с СД) и установить ОУ в исходное состояние (проще говоря, Reset). На первое у нас автоматическая реакция - установка "часов реального времени" значением, приведённым в слове данных. А вот Reset должен дать нам прерывание - прыжок на нулевой адрес кода.
Другие 30 подадресов мы могли выбирать произвольно для своих целей. Мне реально нужно было 10, и я решил "для красоты" дать им максимально возможную дистанцию Хэмминга. А именно, старший бит подадреса я определил битом чётности и потребовал, чтобы сумма всех битов была чётной. Получилось так:
0 0000 - подадрес команд управления,
1 0001 - получить полётное задание (DelayedInt),
1 0010 - получить параметры мишени дальней дистанции (МДД) (DelayedInt),
0 0011 - получить параметры мишени ближней дистанции (МБД) (DelayedInt),
1 0100 - получить аффинную матрицу для МБД (DelayedInt),
0 0101 - получить "сырые данные" с соседнего прибора для стереорежима,
0 0110 - отправить параметры сближения (ради этого всё и затевается!)
1 0111 - не используется (отличается лишь 1 битом от 1 1111),
1 1000 - отправить телеметрию,
0 1001 - отправить изображение (ImmInt),
0 1010 - отправить дамп памяти (ImmInt),
1 1011 - не используется (отличается лишь 1 битом от 1 1111),
0 1100 - отправить "сырые данные" соседнему прибору для стереорежима,
1 1101 - не используется (отличается лишь 1 битом от 1 1111),
1 1110 - не используется (отличается лишь 1 битом от 1 1111),
1 1111 - подадрес команд управления.
Итого, кроме прерывания Reset, нам нужно ещё 6 прерываний, причём 2 из них - "мгновенные", ImmInt (от слова Immediate) т.е мы получили командное слово - и ТУТ ЖЕ (как можно быстрее) сформировали прерывание. Другие 4 - "задержанные" - прежде, чем их сформировать, надо получить весь массив данных, и только если он был получен без проблем, совпал заголовок массива и контрольная сумма - выдавать прерывание!
Процессор QuatCore должен получить сам сигнал Interrupt длительностью в 1 такт, а также номер прерывания, IntNum, причём хотелось бы распихать все эти прерывания в 3-битные значения, раз уж их 7 штук всего.
Чтобы вызвать прерывание Reset, нужно проверить, что подадрес 0 или 31, и в это время поле "число слов данных" равно строго 8, ну и заодно - что команда адресована нам или "всем подряд", и что ровно сейчас мы получили корректное комадное слово (а не дешифруем какой-то мусор на шине данных).
Для проверки на все остальные прерывания, как оказывается, надо задействовать хотя бы 4 бита подадреса из 5, и сократить это количество не получится - я специально себе программку написал, которая устроила прямой перебор. Ну, она мне ещё пригодится, поскольку Quartus категорически не желает упрощать выражения, в которых используются значения 'x' (don't care), тупо приравнивая их всех к нулю...
Но это, на самом деле, не так уж плохо. Функция от 4 бит помещается в 1 ЛЭ в ПЛИС, эка невидаль.
А вот с номером прерывания мне, наконец-то, повезло. Оказалось, что мне вообще не нужны дополнительные регистры или логика, ВСЁ УЖЕ ЕСТЬ! Двумя младшими битами номера прерывания я поставлю 2 младших бита подадреса, которые я всяко запоминал после получения командного слова, чтобы проверить заголовок массива (каждому подадресу соответствует свой). А старшим битом я ставлю признак "Приём/передача", где "передача" от нашего прибора контроллеру шины (условно, "бортовому компьютеру") соответствует единице.
И вот что получается. Те сообщения, которые не должны вызывать прерывания, нас не интересуют, пущай номер прерывания равен чему угодно, QuatCore туда попросту и смотреть не будет, пока сигнал прерывания не выработался. Смотрим сообщения с прерываниями:
0 01 = 1 - получить полётное задание,
0 10 = 2 - получить параметры МДД,
0 11 = 3 - получить параметры МБД,
0 00 = 0 - получить аффинную матрицу МБД,
1 01 = 5 - отправить изображение,
1 10 = 6 - отправить дамп памяти.
Ага, ни одной коллизии пока, это уже приятно. Но теперь нам сюда надо впихнуть Reset. И тут я полез в ГОСТ Р 52070-2003 и вычитал: во всех командах управления без слова данных (к которым относится и Reset), признак "Приём/передача" должен равняться ЕДИНИЦЕ. И тогда наша таблица дополняется следующим образом:
0 00 = 0 - получить аффинную матрицу МБД,
0 01 = 1 - получить полётное задание,
0 10 = 2 - получить параметры МДД,
0 11 = 3 - получить параметры МБД,
1 00 = 4 - Reset (подадрес 0),
1 01 = 5 - отправить изображение,
1 10 = 6 - отправить дамп памяти,
1 11 = 7 - Reset (подадрес 31)
Как говорится, чуть не упал со стула. Впрочем, должно же было когда-то повезти? До этого моя затея с большой дистанцией Хэмминга усложняла декодирование (и она была осмысленна поначалу, но когда нас всё равно попросили для каждого подадреса выдавать 16-битный уникальный "заголовок массива" и там я поставил коды Рида-Мюллера с дистанцией между двумя разными как минимум 8, смысл практически испарился). Зная подадрес, не так-то просто определить, этот подадрес у нас на приём или на передачу? Так-то можно было подадреса для приёма и для передачи по-разному использовать, но опять же, не хотелось, перепутав всего один бит в командном слове, "наломать дров", поэтому под приём и передачу были выбраны разные подадреса. Ну так оказалось: как я не расположу эти свои 10 подадресов (но чтобы отличались не менее чем 2 битами друг от друга и от команд управления) - не выйдет так, чтобы один бит прямо сказал, приём или передача. Или хотя бы 2 бита - их оказалось нужно минимум 3. Да и сама проверка правильности подадреса требовала относительно сложной логики, от 5 входов, без возможности каскадирования по И / ИЛИ.
Пока что проверил на симуляторе формирование прерываний и их номеров - всё работает. Сегодня подключил прерывания к QuatCore, и скомпилировал тестовую программу, которая должна их обрабатывать. Завтра впервые попробую штатно поработать по МКО, а не по UART, как делал это до сих пор...