Вот вам микропрограмма
{#####################################################################################################################}
{#####################################################################################################################}
{#### S2K 25 Мар. 2004 ####}
{#### 16 Янв. 2004 ####}
{#### ------------------------------------------------------ ####}
{#### Ввод изображений с растрового электронного микроскопа. ####}
{#### ------------------------------------------------------ ####}
{#### ####}
{#### Оборудованине ####}
{#### ------------------------- ####}
{#### Ввод осуществляется через АЦП плату L-783, оснащённую микроконтроллером ADSP-2186. Тактовая частота ####}
{#### контроллера 40 Mhz, длительность команды 25 наносекунд. Сигнал яркости подключён к одному из аналоговах ####}
{#### входов, сигналы строчной и кадровой синхронизаций - к цифровым входам. Плата через PCI шину соединена ####}
{#### с персональным компьютером (ПК). ПК загружает в плату управляющую программу и параметры управления ####}
{#### Плата постоянно отслеживает появление начала строк и кадров, собирает статистику строк и кадров и ####}
{#### обслуживает запросы от ПК. ####}
{#### ####}
{#### Функционирование ####}
{#### ------------------------- ####}
{#### Загруженная в плату программа постоянно отслеживает появление начала строк и кадров и собирает статистику ####}
{#### - количество замеченных кадров и количество строк в кадре и обслуживает следующие запросы от ПК: ####}
{#### ####}
{#### 1. Начать передачу данных в ПК ####}
{#### 2. Остановить передачу данных в ПК ####}
{#### 3. Выбрать тестовую картинку ####}
{#### ####}
{#### До начала передачи ПК устанавливает в плате пять параметров: ####}
{#### 1. Количество кадров для передачи ####}
{#### 2. Количество строк в кадре для передачи ####}
{#### 3. Количество пикселов в строке для передачи ####}
{#### 4. Величину делителя тактирования АЦП (частоту дискретизации пикселов) ####}
{#### 5. Режим передачи - непрерывный или покадровый ####}
{#### ####}
{#### По запросу "Начать передачу" начинается передача данных в ПК. ####}
{#### Передача возможна в двух вариантах - непрерывно и покадрово. ####}
{#### В непрерывном режиме передача начинается сразу же после приёма запроса на передачу и оканчиватся по приёму ####}
{#### запроса "Остановить передачу". В покадровом режиме передача начинается по обнаружении начала кадра и ####}
{#### заканчивается после того, как передано заказанное числа кадров. ####}
{#### Передаваемые в ПК данные представлют собой поток, состоящий из пикселов и маркеров - пикселы несут ####}
{#### информацию о яркости, а маркеры - временную информацию, в частности, о моментах появления сигналов ####}
{#### синхронизации. Формат пикселов и маркеров следующий: ####}
{#### Пиксел: 0bbb - 2 байта, старшие 4 разряда ведущего байта - нули, 12 младших разрядов содержат яркость ####}
{#### Маркер: hhhh.ssss.MMMM.mmmm.tttt - 10 байт, старшие 4 разряда ведущего байта - не нули ####}
{#### hhhh - заголовок (он же идентификатор) маркера ####}
{#### ssss - порядковый номер маркера в потоке ####}
{#### MMMM.mmmm.tttt - время рождения маркера(прошедшее с момента загрузки программы в плату) ####}
{#### MMMM - минуты ####}
{#### mmmm - миллисекунды ####}
{#### tttt - обратный счётчик (дополнение до 400) тактов в терминах 25 наносекунд ####}
{#### Генерируются следующие маркеры: ####}
{#### 'FB' 4642 - начало кадра - по обнаружении сигнала начала кадра ####}
{#### 'FE' 4645 - конец кадра - по принятии заданного количества строк в кадре ####}
{#### 'FR' 4652 - сброс начала кадра (если включён) - по обнаружении сигнала, обратного началу кадра ####}
{#### 'LB' 4C42 - начало строки - по обнаружении сигнала начала строки ####}
{#### 'LE' 4C45 - конец строки - по принятии заданного количества пикселов в строке ####}
{#### 'LR' 4C52 - сброс начала строки (если включён) - по обнаружении сигнала, обратного началу строки ####}
{#### По запросу "Остановить передачу" передача данных в ПК сразу же прекращается. ####}
{#### По запросу "Выбрать тестовую картинку" в плате готовится один из вариантов тестовой картинки. ####}
{#### Этот запросу ПК следует выдавать при откючённой передаче данных. ####}
{#### ####}
{#### Настройки и варианты ####}
{#### -------------------- ####}
{#### Помимо выше перечисленных параметров передачи данных, задаваемых для каждой передачи, существуют ####}
{#### следующие задаваемые ПК параметры: ####}
{#### 1.Номер аналогового входа, несущего сигнал яркости ####}
{#### 2.Номер цифрового входа, несущего сигнал начала кадра ####}
{#### 3.Номер цифрового входа, несущего сигнал начала строки ####}
{#### 4.Тип сигнала начала кадра - по заднему или переднему фронту ####}
{#### 5.Тип сигнала начала строки - по заднему или переднему фронту ####}
{#### 6.Разрешение на генерацию маркеров обратного хода ####}
{#### 7.Разрешение на симуляцию сигнала яркости ####}
{#### 8.Разрешение на симуляцию сигналов начала кадра и строк ####}
{#### 9.Период и скважность симулируемых сигналов начала кадра и строк ####}
{#### 10.Вариант тестовой картинки ####}
{#### 11.Светлый тон тестовой картинки ####}
{#### 12.Тёмный тон тестовой картинки ####}
{#### ####}
{#### Симуляция ####}
{#### ---------- ####}
{#### Симуляция предназначена для проверки и наладки взаимодействия с платой, в частности, при отсутсвии ####}
{#### физических сигналов. Временные характеристики работы управляющей программы платы при включённой и ####}
{#### выключенной симуляции практически одинаковы - вернее, при симуляции плата работает чуть-чуть медленнее ####}
{#### чем с реальными сигналами. Функционирует симуляция следующим образом: ####}
{#### При включённой симуляции сигналов синхронизации, сигналы начала кадра и строки берутся не с цифровых ####}
{#### входов, а генерируются таймером платы в соответствии с настройкой четырёх внутренних программных таймеров ####}
{#### - таймеры 1 и 2 задают сигнал начала кадра, таймеры 3 и 4 - сигнал начала строки. Первый таймер в паре ####}
{#### определяет длительность высокого уровня сигнала, второй - низкого. Периоды всех четырёх таймеров могут ####}
{#### быть заданы со стороны ПК. ####}
{#### При включённой симуляции сигнала яркости, яркость берётся не с аналогового входа, а из самой платы - ####}
{#### из заранее сгенериованной тестовой картинки. Имеется 8 вариантов тестовой картинки. Некоторые из картинок ####}
{#### состоят из перемежающихся светлых и тёмных тонов. Конкретная яркость этих тонов и вариант тестовой ####}
{#### картинки могут быть заданы со стороны ПК. ####}
{#### ####}
{#####################################################################################################################}
{#####################################################################################################################}
{-- --------------------------------------------------------- ----------------------------------------------------------}
{-- --------------------------------------------------------- ----------------------------------------------------------}
{-- --------------------------------------------------------- ----------------------------------------------------------}
{-- --------------------------------------------------------- ----------------------------------------------------------}
{-- --------------------------------------------------------- ----------------------------------------------------------}
{ Распределение ресурсов: }
{--------------------------------------------- Адресные генераторы ---------------------------------------------------}
{ i0,l0,m0 - позиция в кольцевом буфере, откуда ПК следует брать буферированные данные по сигналу прерывания }
{ i1,l1,m1 - позиция в кольцевом буфере, куда складываются данные от АЦП }
{ i2,l2,m2 - не используется }
{ i3,l3,m3 - не используется }
{ i4,l4,m4 - буфер принятых от ПК команд }
{ i5,l5,m5 - генератор тестовой картинки - список начала строк }
{ i6,l6,m6 - генератор тестовой картинки - значения пикселов }
{ i7,l7,m7 - общего назначения, используются для промежуточных вычислений }
{--------------------------------------------- Первый банк регистров -------------------------------------------------}
{ ar, ax0, ax1, ay0, ay1 - общего назначения, используются для промежуточных вычислений }
{ аf - зарезервирован для проверки управляющих полей }
{ my0 - зарезервирован для хранения сигнала кадровый синхронизации }
{ my1 - зарезервирован для хранения сигнала строчной синхронизации }
{ mr0 - зарезервирован для хранения управляющих полей }
{ mr1 - зарезервирован для хранения селектора логческого канала АЦП, к которому подключён сигнал яркости }
{ mr2 - не используется }
{ sr - не используется }
{-- --------------------------------------------------------- ----------------------------------------------------------}
{ SPORT0 - не используется }
{ SPORT1 - тактирует АЦП }
{ Timer - увеличивает показания часов каждые 10 микросекунд }
{ BDMA - не используется }
{ Второй банк регистров - не используется }
{-- --------------------------------------------------------- ----------------------------------------------------------}
{=====================================================================================================================}
{ Определяеи имя программы }
{-- --------------------------------------------------------- ----------------------------------------------------------}
.MODULE/ABS=0/SEG=int_pm_user main_program;
.PAGEWIDTH 200;
.PAGELENGTH 1000;
{=====================================================================================================================}
{ Создаём макросы для распределения памяти }
{-- --------------------------------------------------------- ----------------------------------------------------------}
#define atPc(xxx,yyy,zzz) .VAR/SEG=INT_PM_USER/ABS=xxx/pM/RAM/CIRC yyy[zzz]; { цикл.буфер в PM - позиция, имя, длина }
#define atDc(xxx,yyy,zzz) .VAR/SEG=INT_DM_USER/ABS=xxx/dm/RAM/CIRC yyy[zzz]; { цикл.буфер в DM - позиция, имя, длина }
#define atDt(xxx,yyy,zzz) .VAR/SEG=INT_DM_USER/ABS=xxx/dm/RAM yyy[zzz]; { массив в DM - позиция, имя, длина }
#define atDm(xxx,yyy,zzz) .VAR/SEG=INT_DM_USER/ABS=xxx/dm/RAM yyy; .INIT yyy: zzz;{ ячейка DM - позиция, имя, значение}
{-- --------------------------------------------------------- ----------------------------------------------------------}
{ Распределяем память данных }
{ Область 0x2800 - 0x2D77 в памяти данных вместе с именами и комментариями (и её копия в по адресу 0x3800) }
{ унаследована от "родной" программы управления платой и нужна исключительно для корректного взаимодействия }
{ с драйвером ПК в части обслужвания запросов от ПК и формирования потока данных в ПК. }
{-- --------------------------------------------------------- ----------------------------------------------------------}
{----- 0x2000-------------------------------------- Начало памяти данных----------------------------------------------}
atDc ( 0x2000, ADC_Buffer , 2048 ) { Круговой буфер на 2K отсчётов от АЦП в памяти данных }
atDt ( 0x2A00, Control_Table , 96 ) { }
atDt ( 0x2B00, ScaleFactorArray , 96 ) { }
atDt ( 0x2C00, ZeroOffsetArray , 96 ) { }
atDt ( 0x2D00, ScaleFactor , 4 ) { Множители для всех усилений/каналов }
atDt ( 0x2D04, ZeroOffset , 4 ) { Смещения нуля для всех усилений/каналов }
atDm ( 0x2D08, Control_Table_Lenght , 0x8 ) { Длина Control Table }
atDm ( 0x2D09, Control_Table_Lenght2 , 0x6 ) { Длина Control Table-1 }
atDm ( 0x2D0A, Counter , 0x0 ) { }
atDm ( 0x2D0B, KadrPeriod , 0 ) { }
atDm ( 0x2D40, Ready , 0 ) { Флаг готовности к работе после загрузки DSP }
atDm ( 0x2D41, TMode1 , 0x333 ) { Test Var 1 }
atDm ( 0x2D42, TMode2 , 0x777 ) { Test Var 2 }
atDm ( 0x2D48, DSP_Type , 0x0 ) { Для ADSP-2186 - DSP_Type=2 }
atDm ( 0x2D49, Command , 0x0 ) { Command for IRQ2 DSP }
atDm ( 0x2D4A, FirstSampleDelay , 0x50 ) { 2.7 мкс - задержка для первого отсчета в FIFO буфере АЦП }
atDm ( 0x2D4C, TtlOut , 0x0 ) { Ttl Out var and PF0 mode }
atDm ( 0x2D4D, TtlIn , 0x0 ) { Ttl in var }
atDm ( 0x2D4E, UartRate , 23 ) { Только для !!!L-761!!! частота SPORT0 для работы как UART }
atDm ( 0x2D4F, DacFifoPointer , 0xC00 ) { DAC Fifo Pointer }
atDm ( 0x2D50, AdcFifoPointer , 0x2000 ) { ADC Fifo Pointer }
atDm ( 0x2D51, IsAdcSample , 0x0 ) { Флажок, что было прерывание от АЦП }
atDm ( 0x2D52, TestLoadVar , 0x77 ) { Test Variable }
atDm ( 0x2D53, ADC_Rate , 100 ) { ADC Rate Variable }
atDm ( 0x2D54, Inter_Kadr_Delay , 0x0 ) { Величина межкадровой задержки в единицах клоков SCLK SPORT1 }
atDm ( 0x2D55, DAC_Rate , 49 ) { DAC Rate Variable }
atDm ( 0x2D56, DAC_Value , 0x0 ) { Выходное значение ЦАП'а }
atDm ( 0x2D57, EnableIrq , 0x0 ) { Enable Irq PC }
atDm ( 0x2D58, IrqStep , 0x400 ) { Step in FIFO for IRQ PC }
atDm ( 0x2D59, IrqSampleCounter , 0x0 ) { Счетчик числа отсчетов для генерации прерывания в PC }
atDm ( 0x2D5A, IrqDataAddress , 0x2000 ) { Базовый адрес, где можно брать данные, если было прерывание в PC }
atDm ( 0x2D5B, EnableIrqValue , 0x0 ) { Значение, которое передается в переменную EnableIrq }
atDm ( 0x2D5C, AdSample , 0x0 ) { Значение однократного отсчета с АЦП }
atDm ( 0x2D5D, AdChannel , 0x0 ) { Логический номер канала для однократного отсчета с АЦП }
atDm ( 0x2D5E, SCLK0_DIV , 0x7 ) { Делитель SCLK0_DIV для работы ЦАП'а }
atDm ( 0x2D5F, IMASK_VALUE , 0x200 ) { }
atDm ( 0x2D60, IsCorrectionEnable , 0x0 ) { Флажок разрешения/запрещения корректировки входных данных }
atDm ( 0x2D61, TopStack , 0x0 ) { }
atDm ( 0x2D62, ADC_Enable , 0x1 ) { Флажок разрешения/запрещения работы АЦП }
atDm ( 0x2D63, AdcFifoBaseAddress , 0x2000 ) { Текущий базовый адрес FIFO буфера АЦП }
atDm ( 0x2D64, ADCFifoBaseAddressIndex, 0x2 ) { Индекс базового адреса FIFO буфера АЦП }
atDm ( 0x2D65, AdcFifoLength , 0x800 ) { Текущая длина FIFO буфера АЦП }
atDm ( 0x2D66, NewADCFifoLength , 0x800 ) { Длина FIFO буфера АЦП, которую хотелось бы установить }
atDm ( 0x2D67, EnableDacStream , 0x0 ) { Флажок разрешения/запрещения работы ЦАП в режиме вывода из буфера }
atDm ( 0x2D68, DacFifoBaseAddress , 0xC00 ) { Текущий базовый адреса FIFO буфера ЦАП }
atDm ( 0x2D69, DacFifoLength , 0x400 ) { Текущая длина FIFO буфера ЦАП }
atDm ( 0x2D6A, NewDacFifoLength , 0x400 ) { Длина FIFO буфера ЦАП, которую хотелось бы установить }
atDm ( 0x2D6B, PM_Data , 0x0 ) { }
atDm ( 0x2D6C, PX_Reg , 0x0 ) { }
atDm ( 0x2D70, SynchroType , 0x0 ) { }
atDm ( 0x2D71, TtlSynchroFlag , 0x0 ) { }
atDm ( 0x2D72, AdSynchroFlag , 0x0 ) { }
atDm ( 0x2D73, SynchroAdChannel , 0x0 ) { }
atDm ( 0x2D74, SynchroAdPorog , 0x0 ) { }
atDm ( 0x2D75, SynchroAdMode , 0x0 ) { }
atDm ( 0x2D76, SynchroAdSensitivity , 0x0 ) { }
atDm ( 0x2D77, AdSynchroStep , 0x0 ) { }
{----- 0x2E00-------------------------------------- А это наши данные-------------------------------------------------}
{ -----------внешнее управление------------------------------------ }
{ Биты 0-2 - вариант тестовой картинки }
.const Framed_transfer = 3; { Бит 3 - включен режим покадровой передачи данных }
.const Analog_simul_enabled = 4; { Бит 4 - включена симуляция сигнала яркости }
.const Digital_simul_enabled = 5; { Бит 5 - включена симуляция цифровых сигналов }
.const Backtrack_markers_enabled = 6; { Бит 6 - включен вывод маркеров обратного хода в поток }
.const Control_entered = 7; { Бит 7 - запрос на ввод внешнего управления }
{ -----------внутреннее управление--------------------------------- }
.const Stream_enabled = 8; { Бит 8 - включена передача данных в ПК }
.const Request_to_start_stream = 9; { Бит 9 - запрос на запуск передачи данных в ПК }
.const Reserved_1 = 10; { Бит 10 - резерв }
.const Timer_5_enabled = 11; { Бит 11 - включён таймер 5 }
.const Timer_4_enabled = 12; { Бит 12 - включён таймер 4 }
.const Timer_3_enabled = 13; { Бит 13 - включён таймер 3 }
.const Timer_2_enabled = 14; { Бит 14 - включён таймер 2 }
.const Timer_1_enabled = 15; { Бит 15 - включён таймер 1 }
{-------------Принимаемые от ПК-------------------------------------}
atDm ( 0x2E00, Controls , 0x0004 ) { Управление - младшие 8 рвзрядов могут быть заданы извне }
atDm ( 0x2E01, ADC_channel_selector , 0x0030 ) { 1ый канал с общей землёй xxxxxxxx.rr1ccccc rr-размах ccccc-канал }
atDm ( 0x2E02, Frame_signal_mask , 0x4000 ) { Маска сигнала кадровой синхронизации в группе цифровых сигналов }
atDm ( 0x2E03, Frame_start_type , 0x0000 ) { 0- начало по заднему фронту, совпадающая с маской - по переднему }
atDm ( 0x2E04, Line_signal_mask , 0x8000 ) { Маска сигнала строчной синхронизации в группе цифровых сигналов }
atDm ( 0x2E05, Line_start_type , 0x0000 ) { 0- начало по заднему фронту, совпадающая с маской - по переднему }
atDm ( 0x2E06, ADC_clock_divider , 26 ) { 650ns/пиксел тестовый кадр - 1400 строк за 3.5 секунды при 40 Mhz }
atDm ( 0x2E07, Pixels_per_line_accept , 1333 ) { 1400 - 20% }
atDm ( 0x2E08, Lines_per_frame_accept , 999 ) { 900 + 10% }
atDm ( 0x2E09, Frames_to_send , 1 ) { }
atDm ( 0x2E0A, Dark_tone , 0x000f ) { Используется для генерации тестовой картинки }
atDm ( 0x2E0B, Light_tone , 0x0ff0 ) { Используется для генерации тестовой картинки }
atDm ( 0x2E0C, Timer_step , 400 ) { Прерывание таймера через 10 мкс (400 циклов, цикл=25нсек) }
atDm ( 0x2E0D, Square_side_size , 100 ) { Размер ребра квадрата тестовой картинки }
atDm ( 0x2E0E, Timer_5_low , 1 ) { 4-ёх байтовый счётчик в терминах 10 микросекунд }
atDm ( 0x2E0F, Timer_5_high , 1 ) { }
{...................................................................}
atDm ( 0x2E10, Timer_1_low , 0xCE78 ) { Длительность высокого уровня сигнала кадровой синхронизации }
atDm ( 0x2E11, Timer_1_high , 4 ) { 315000*10 = 3150000 uks 3150 ms = 3.15 sec }
atDm ( 0x2E12, Timer_2_low , 0x88B8 ) { Длительность низкого уровня сигнала кадровой синхронизации }
atDm ( 0x2E13, Timer_2_high , 0 ) { 35000 * 10 = 350000 uks = 350 ms = 0.35 sec }
atDm ( 0x2E14, Timer_3_low , 0xC8 ) { Длительность высокого уровня сигнала строчной синхронизации }
atDm ( 0x2E15, Timer_3_high , 0 ) { 200*10 = 2000 uks = 2 ms }
atDm ( 0x2E16, Timer_4_low , 0x32 ) { Длительность низкого уровня сигнала строчной синхронизации }
atDm ( 0x2E17, Timer_4_high , 0 ) { 50*10 = 500 uks = 0.5 ms }
atDm ( 0x2E18, Sequential_number , 0 ) { Порядковый номер маркера }
atDm ( 0x2E19, e19unused , 0x9999 ) { }
atDm ( 0x2E1A, e1Aunused , 0xAAAA ) { }
atDm ( 0x2E1B, e1Bunused , 0xBBBB ) { }
atDm ( 0x2E1C, e1Cunused , 0xCCCC ) { }
atDm ( 0x2E1D, e1Dunused , 0xDDDD ) { }
atDm ( 0x2E1E, e1Eunused , 0xEEEE ) { }
atDm ( 0x2E1F, Data_block_tail , 0 ) { Длина (в словах) и контрольная сумма блока данных }
{-------------Передаваемые в ПК-------------------------------------}
atDm ( 0x2E20, Status , 0 ) { }
atDm ( 0x2E21, Frames_accepted , 0 ) { }
atDm ( 0x2E22, Lines_accepted , 0 ) { }
atDm ( 0x2E23, Frames_sent , 0 ) { }
atDm ( 0x2E24, ADC_handler_size , 0 ) { }
atDm ( 0x2E25, Elapsed_minutes , 0 ) { }
atDm ( 0x2E26, Elapsed_ms , 0 ) { }
atDm ( 0x2E27, Lines_per_frame_last , 0 ) { }
atDm ( 0x2E28, e28unused , 0x8888 ) { }
atDm ( 0x2E29, e29unused , 0x9999 ) { }
atDm ( 0x2E2A, e2Aunused , 0xAAAA ) { }
atDm ( 0x2E2B, e2Bunused , 0xBBBB ) { }
atDm ( 0x2E2C, e2Cunused , 0xCCCC ) { }
atDm ( 0x2E2D, e2Dunused , 0xDDDD ) { }
atDm ( 0x2E2E, e2Eunused , 0xEEEE ) { }
atDm ( 0x2E2F, e2Funused , 0xFFFF ) { }
{-------------Промежуточные данные-----------