Показаны сообщения с ярлыком laboratory. Показать все сообщения
Показаны сообщения с ярлыком laboratory. Показать все сообщения

понедельник, 24 января 2011 г.

ftd2xx library on wine

Сегодня рассмотрим решение проблемы запуска windows-приложений, написанных для различных девайсов и использующих библиотеку ftd2xx (libftd2xx) для связи с ними, под wine. Вначале я кратко расскажу про мотивацию к такой экзотике, потом о принципе реализации и граблях, на которые удалось наступить, и в конце дам ссылочку на патч.

И так, исходные данные, автокоррелятор от Avesta project, подключающийся к ПК по USB, и программа Irtac для работы с прибором. В приборе USB аппаратно реализовано на микросхеме ftdi, что можно увидеть по логам при подключении устройства (dmesg или /var/log/messages). Программа Irtac собрана под windows с использованием коммерческой (закрытой) версии библиотеки ftd2xx. Реализации под linux нет и ждать не приходится, а перегружаться в винду ради одного прибора очень не хочется, тем более, что реально он часто нужен не один. Есть вариант с использованием виртуальной машины. Неопенсорсный virtualbox умеет прокидывать USB в систему, и, например, поляриметр от thorlabs так заставить работать удалось. Ситуацию осложняет то, что такой трюк оборачивается существенными тормозами в работе виртуалки, и Irtac тупо отваливался по таймауту. Под wine сама программа хоть и запускается, но работать с прибором не хочет. Оно и понятно, если я ей подсуну windows-версию библиотеки, то она понятия не имеет как работать с USB  в linux, а linux-версию программа, собранная под винду, по ясным причинам подцепить не сможет. И так, выход один, надо разобраться, как wine реализует свои библиотеки, и написать обёртку (fake) для linux-версии libftd2xx.
Немного рутины - необходимо достать исходники установленного у вас wine, распаковать их, потом наложить прилагаемый патчик, запустить configure и make, а после скопировать ftd2xx.dll.so и ftd2xx.dll.fake в /usr/lib/wine/ftd2xx.dll.so и /usr/lib/wine/fakedlls/ftd2xx.dll (или куда там установлен штатный wine) соответственно. Как получился этот патч? Сначала всё казалось проще пареной репы: у нас есть две библиотеки с идентичными функциями, значит, нам даже толком не надо ничего писать, а просто "связать" вызов функции из программы с той же функцией в нативной библиотеке. Сказано - сделано. Но было бы наивно предполагать, что Irtac сходу заработает, тем более что мы не знаем функции, которые он использует. Для тестирования я взял примеры из libftd2xx1.0.2 и собрал их как под linux, так и под винду (через mingw). Тут количество используемых функций и порядок их вывода строго определён, и можно отследить на каком месте что у нас порушилось. На первом этапе я никак не мог понять, как сделать этот самый вызов функций с одним и тем же названием и метался от простой сборки wine-библиотеки статиком с libftd2xx.a до написания обёртки с другим именем, из которой бы цеплялась нативная библиотека, а сама обёртка использовалась бы нашей fake-либой, и тем самым, мы избежали бы конфликта имён. Однако, найти правильный путь помогла wine-библиотека glu32. Здесь реализовано фактически именно то, что нам необходимо. А вся изюминка кроется в том, что заголовки функций для windows- и для linux-версии ftd2xx немного различаются. Это обстоятельство учтено в ftd2xx.h, и правильные заголовки определяются при сборке define-ами. Нам же необходимо подставить define-ы, которые использовались бы при сборке под виндой (чтобы прога могла найти функции), хотя фактически, собираем мы всё это дело под пингвином. Однако, после этого прозрения вылезла ещё одна проблема, и заключается она вот в чём. Функции, которые мы хотим отдать wine-у на экспорт, перечисляются в ftd2xx.spec, где первый параметр - некий номер функции... Я не понимаю, что это за номер, но на практике, этот номер как-то связан с тем, где именно находится данная конкретная функция. И если мы правильно пишем обёртку, но вместо номера ставим "@", что в соответствии с http://linux.die.net/man/1/winebuild означает автоматическое присвоение номера, то не факт, что этот номер совпадёт с реальным. И при попутке запустить программу получим что-то типа:
wine: Call from 0x7ef918f0 to unimplemented function FTD2XX.dll.32, aborting
wine: Unimplemented function FTD2XX.dll.32 called at address 0x7ef918f0 (thread 0009), starting debugger...
Но это и ключ к разгадке! Если мы знаем, какую именно функцию дергает приложение, а это можно установить по исходникам, то данный вывод означает, что эта функция должна находится по номеру 32, но её там почему-то нет. Ставим этот номер вместо собаки в ftd2xx.spec, и двигаемся дальше...

В результате, я написал обёртки для всех функций из ftd2xx.h кроме тех, где есть префикс W32 (просто я не знаю как уложить их параметры в концепцию wine). Получилось 49 штук. Из них я подобрал номера к 16-ти. Для этой процедуры я использовал примеры  BitMode, EEPROM/read, LargeRead, Simple и Timeouts. Вывод данных программ был идентичен про запуске в linux, и при запуске под wine-ом. В качестве "прибора" использовалась заглушка в виде микросхемы FT232RL с замкнутыми Rx/Tx и питанием от USB-порта. В ближайшее время буду пробовать на реальном железе.
Использование данного материала, а также поправки и исправления неточностей только приветствуются.
Патчик можно найти тут.

upd: Оказывается, кое-что всё-таки "уже украдено до нас". Так, вот тут автор ещё в 2005 году сделал вызов основных функций через libusb. Кроме того, он приводит spec, в котором уже указаны адреса для всех функций.. Что-то мне подсказывает, что их узнать можно гораздо проще, чем я описал выше...

upd2: Поразительно, но мне действительно удалось заставить эту прогу корректно работать с прибором! Однако, обнаружилось пара нюансов:
1. Значения Timeout-ов и LatencyTimer пришлось увеличить в 10 раз возможно, хватило бы и пары, но взял с запасом, и оно попёрло)
2. Если функция FT_ListDevices используется с флагом FT_LIST_BY_INDEX, то перед вызовом нативной функции стоит вызвать FT_CreateDeviceInfoList, т.к. без этого всё или виснет или crash-ится.
Обновлённый патчик со всеми этими изменениями, а также с некоторым количеством отладочной информации для wine-1.2_rc7 можно найти тут.

понедельник, 5 октября 2009 г.

MailMan для малого предприятия

Введение
Как часто вам приходилось рассылать объявления на несколько адресатов? Вести обсуждение проблемы по почте с несколькими людьми одновременно? Искать в архиве писем решение проблемы годичной давности?
Оказывается уже давно есть простые иструменны, эффективно решающие эти проблемы - списки рассылки (http://ru.wikipedia.org/wiki/Рассылка_электронной_почты).
Принцип работы прост - для того чтобы распространить сообщение между подписчиками необходимо отправить письмо на специальный e-mail рассылки. Примером рабочей рассылки может служить http://lists.altlinux.org/ где идёт постоянное обсуждение проблем разработки и использования решений ALT Linux между членами сообщества. Применение такого подхода в рамках малого предприятия позволит структурировать рассылку объявлений, вынести часть дискуссий в рассылку и даёт возможность каждому участнику быть в курсе.
Для полноценного использования списков рассылки требуется, чтобы сервис работал на сервере с доменным именем. Однако если с регистрацией заморачиваться не хочется, а рассылки хочется, то можно немного пораскинуть мозгами, и поднять сервис на локальной машине а пересылку писем вести через сторонний внешний сервер. В качестве сервиса управления рассылками выбран один из наиболее популярных - mailman, и о том, как заставить его корректно работать из локальной сети, и пойдёт речь дальше.

Необходимый инструментарий
В качестве дистрибутива я использую ALT Linux 4.1, где всё необходимое есть в пакетах, и это надо только поставить и настроить. И так, ставим MailMan. Он требует, чтобы на машине работал сервер электронной почты. Ставим postfix, на всякий случай прихватываем модули для авторизации по sasl и отправку через cyrus. Fetchmail для сбора почты снаружи и передаци её postfix-у.
Алгоритм следующий. Поднимаем postfix, учим его отправлять локальные письма напрямую, а все остальные через внешний smtp. Создаём необходимые ящики на любимом сервере, пусть будет example.mail.ru. Адресов понадобится несколько, хотябы 4 на одну рассылку. Объясняем postfix-у как авторизовываться на smtp в зависимости от отправителя. Настраиваем fetchmail на проверку новосозданных ящиков и запускаем демоном. Запускаем MailMan и настраиваем там нашу рассылку.

Настройка postfix
Тут наступил на давольно редкие грабли. Почтовый сервер, на котором я остановился, требовал авторизацию открытым текстом поверх TLS. Погуглив и почитав маны на postfix, понял, что обучить его этому нельзя. Решение следующее - запускаем демоном stunnel:

stunnel -c -r example.mail.ru:465 -d 11125
В /etc/postfix/main.cf добавляем следующее:

relayhost = [127.0.0.1]:11125 #хост для отправки писем наружу
mynetworks = 127.0.0.1 #обслуживаем только локальные запросы
smtp_sender_dependent_authentication = yes #в зависимости от отправителья выбираем аккаунт для smtp
sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relayhost #список акаунтов
smtp_sasl_auth_enable = yes #говорим о необходимости регистрации
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd #перечисляем используемые аккаунты
smtp_sasl_security_options = #очищаем опции защиты
transport_maps = hash:/etc/postfix/transport #перечисляем случаи, когда почта должна доставлятся локально
myorigin = localhost #имя нашего хоста :)
recipient_canonical_maps = hash:/etc/postfix/recipient_canonical #таблица замен

alias_maps = hash:/etc/postfix/aliases, hash:/etc/mailman/aliases #файлы с алиасами

Тут стоит заметить, что если при отправке письма обратный адрес, и аккаунт, с которого произошла отправка, будут не совпадать, то такое письмо рискует попасть в спам. По крайней мере google делает именно так.
Далее полагаем, что мы хотим создать список рассылки mylists.

/etc/postfix/sender_relayhost
mylists@example.mail.ru [127.0.0.1]:11125 #адрес, на который необходимо посылать письма в рассылку
mylists-bounces@example.mail.ru [127.0.0.1]:11125 #отсюда будут приходить письма из рассылки
mylists-request@example.mail.ru [127.0.0.1]:11125 #отсюда будет приходить запрос на регистрацию
mylists-owner@example.mail.ru [127.0.0.1]:11125 #сюда надо писать письма для владельца рассылки
По хорошему, mailman-у надо ещё столько же адресов для связи с администраторами, можераторами и пр, но этот функционал мы не пользуем, и адреса, соответственно, не создаём.

/etc/postfix/sasl_passwd #перечисляем используемые аккаунты с явками и паролями
mylists@example.mail.ru mylists:xxx
mylists-bounces@example.mail.ru mylists:xxx
mylists-request@example.mail.ru mylists:xxx
mylists-owner@example.mail.ru mylists:xxx
/etc/postfix/transport
localhost.localdomain local: #письма с таким доменом отправляем локально
localhost local:

/etc/postfix/recipient_canonical
@yourhost.yourdomain @localhost.localdomain

Эта таблица требуется в том случае, если и машини есть какие-то абстрактные имя и домен, и они пролазят в заголовки писем или мешают корректно работать transport-ам. Хотя наверно это содержимое можно было бы просто перенсти в /etc/postfix/transport

На этом с отправкой писем вроде всё, хотя мелкие детали я мог и упустить. Перед дальнейшим шагом необходимо проверить работоспособность сервера, например mutt-ом. Перед запуском postfix не забываем сделать postmap для всех хешей.

Настройка fetchmail
Здесь всё гораздо проще.

cat ~/.fetchmailrc
set syslog
defaults protocol pop3, timeout 90, nokeep, fetchall, ssl
poll "example.mail.ru" user "mylists" there with password "infibgal" is mylists here;
poll "example.mail.ru" user "mylists-request" there with password "xxx" is mylists-request here;
poll "example.mail.ru" user "mylists-bounces" there with password "xxx" is mylists-bounces here;
poll "example.mail.ru" user "mylists-owner" there with password "xxx" is mylists-owner here;

Локально пользователей mylists* может не быть. Необходимые алиасы настраиваются автоматически mailman-ом при создании рассылки mylists.
Запускаем fetchmail демоном:
#fetchmail -d 90
Запуск можно прописать в загрузочные скрипты.

Настройка mailman
Теперь у нас всё подготовлено для работы mailman-а. Первоначальную настройку можно выполнить через alterator. При этом в качестве адреса веб-сайта обязательно указываем ip нашей машины, или ммылки внутри mailman-а не будут работать. В качестве адресо почтового сервера указываем example.mail.ru. Используемый MTA - postfix.

После этого идём не страничку админимстрирования http://наш.ip.ад.рес/mailman/admin и создаём первый список рассылки mylists. После этого обязательно обновим алиасы postfix-а, запустив newaliaces.
Теоретически, всё должно работать, если я не забыл каких-нить мелочей. Ура!

вторник, 25 марта 2008 г.

Python как инструмент обработки экспериментальных данных

Обработка экспериментальных данных... Как обрабатывать, в чём обрабатывать? Если ответ на первый вопрос как правило понятен, то со вторым вопросом всё гораздо сложнее. Далее расскажу о некоторых своих изысканиях последней недели, касательно именно того, в чём обрабатывать.

И так, сам эксперимент состоял в том, что на выходе я имел некие графики спектров лазера в зависимости от мощности накачки. Поведение спектров, а именно их ширины, как основного параметра - не тривиально, и под это дело в лаборатории была разработана теория, которую было необходимо проверить, установить пределы применимости. В теории присутствовал подгоночный параметр, который должен быть постоянен при всех значениях мощности.

Но в данном контексте это всё не суть, а суть в том, что имею 25 .csv файлов со спектрами, которые надо отнормировать, из которых надо извлечь мощность, ширину, внутререзонаторный спектр, подогнать теоретическим спектром и строить всевозможные графики зависимостей этих величин, дабы понять что вообще там происходит.

И так, мне понадобиться: работа с болшьими массивами чисел, численное интегрирование, интерполяция, численное нахождение корней уравнения F(x)=0 где F - нелинейная функция, аппроксимация по методу наименьших квадратов произвольной функцией.

Выбираем средства: 1.Origin - хорош при обработке малого числа графиков, но в данном случае терпит полный крах, т.к. мне проще будет повеситься, чем работать в нём с таким количеством данных, а это ведь только начало. 2.MathCad - курит в сторонке, т.к. с его интерфейсом я без матов работать не могу - порой кучу усилий надо приложить, чтобы только скобаку поставить в нужном месте, к тому же нет версии под lin. 3.MATLAB - отличный инструмент, но его функционал явно избыточен. 4.SciLab - замечательная штука, в которой есть всё то, что мне необходимо, и которую я уже было подорвался использовать для всех нужд, однако столкнулся с проблемой: скриптами можно организовать пакетную обработку данных (нормировку, аппроксимацию и пр.), но когда появляется необходимость максимально быстро сконструировать график зависимости одной величины, определяемой из пакетной обработки, от другой, приходиться поломать голову. По сути, это язык программирования высокого уровня, но это функциональный язык, в то время как объектно-ориентированный подход мог бы дать большую гибкость. 5. Python - ооп язык программирования высокого уровня в котором я и нашел спасение:

Python как инструмент обработки экспериментальных данных

И так, нам потребуются модули numpy, matplotlib, scipy. Эти модули предоставляют замечательный функционал, включающий всё, что мне может понадобиться на данном этапе.

Вся изюминка кроется в реализации обработки эксперимента: создаем класс "spectr" который будет служить обёрткой для экспериментально-измеренного спектра. Добавляем в качестве методов всё, что мы можем с этим спектром сделать: умножение на другой спектр, центральная блина волны, пиковая мощность, ширина на полувысоте, нормировка по мощности, умножение на константу, обрезание шума, сохранение в файл, открытие из файла. Это краткий список того, что мне понадобилось в первую очередь, что важно, список этот легко может быть расширен в дальнейшем. Далее, создаём класс, описывающий нашу теоретическую модель, который включает в себя все формулы, все параметры, методы аппроксимации, методы расчёта теоретических параметров. Теперь создавая несколько экземпляров класса с разными параметрами легко можно сравнить влияние этих самых параметров на предсказания модели, которые в свою очередь легко сравнить с реальными данными.

Основной скрипт обработки читает экспериментальные спектры, создавая из них массив объектов класса "spectr" в цикле извлекает параметры полуширины, мощности как на выходе, так и внутри резонатора, проводит аппроксимацию и поиск подгоночного параметра для каждого участка спектра. Теперь, имея в руках все эти данные одновременно, можно легко с ними оперировать, концентрируясь на физике дела, которая сейчас, не обременённая техническими деталями обработки, становиться весьма интересной.

среда, 12 марта 2008 г.

python-qt-qwt

И так, захотелось мне писать проги с "окошками" за минимальное время и с максимальной быстротой (т.к. возможно вскоре это будет производственной необходимостью). Кроме того, поскольку контора сейчас сидит под виндами, а в дальнейшем стоит планировать хотя бы частичное внедрение пингвина, то уже сейчас стоит закладываться на кросплатформенность, которая присуща всем 3-м инструментам.

Почему питон? - потому, что легкий синтаксис, потому что много модулей, потому что кросплатформенный и в конце концов, потому что имхо модно.

Почему Qt? - потому что обывателя интересуют окошки, потому что мне понравились методы использования сигналов/слотов, потому что всё грамотно объектно-ориентировано.

При чём тут qwt? - qwt, как известно, библиотека для qt, которая предоставляет различные элементы оформления, востребованные в научной среде (plot с автомасштабированием, различные крутилки, ползунки и пр), так что прикрутить это к нашим окошкам было бы очень недурно.

Отдельной строкой стоит отметить, что интерфейс на Qt может быть легко "нарисован" в дизайнере, а получившейся .ui-файл транслирован на питон, т.о. руками остаётся лишь написать обработчики для элементов окна, и должна получиться вполне рабочая прога.

И вот, руководствуясь этими соображениями и подогреваемый желанием лёгкой наживы, я начал своё "хождение по мукам"....

...продолжение следует.

среда, 20 февраля 2008 г.

Спецификация USB, заметки по сути.

USB - универсальная последовательная шина, позволяющая подключать до 127 устройств самого различного плана и имеющая пропускную способность до 480Мбит/сек (USB 2.0), бла-бла и бла-бла... Это все знают, это можно легко прочитать на той же вики и интересно это может быть лишь для общего развития. ИМХО куда интересней собрать какую-нить свою поделку взаимодействущую с ПК через эту шину.

Задача:

Организовать soft-usb на МК AVR серии ATmega.

Но перво-наперво надо понять как в принципе работает эта шина.

Пойдем путём настоящих джедаев и скачаем с www.usb.org полную версию спецификации 2.0...

Признаться, стиль в котором там всё составлено мне совершенно не понравился, уж слишком много воды, повторений и пр.. Можно было, конечно, написать тоже более лаконично и логично, но признаем что это просто адский труд и скажем спасибо разработчикам за то, что имеем. И так, постараюсь выделить самую суть, которую просто необходимо понимать для того чтобы работать с usb на самом низком уровне.

  1. Все транзакции определяются хостом: устройство должно принять данные по запросу хоста, устройство может передать данные только после того как хост спросит, нет ли данных на отправку и пр.
  2. Каждое устройство при подключении проходит стадию конфигурирования: получает от хоста уникальный адрес, передаёт информацию о типе, о производителе (об этом чуть позже).
  3. Хост идентифицирует каждое устройство по его адресу на шине, поле адреса занимает 7 байт, отсюда максимальное число устройств на шине - 127 (нулевой используется при конфигурации и не может быть назначен в качестве рабочего)
  4. Данные по шине передаются пакетами, каждый пакет начинается с поля синхронизации, затем идёт поле PID, определяющее тип пакета, дальнейший формат определяется типом пакета. Особо стоит обратить внимание на типы Token, DATA, Handshake. (В спецификации описание взаимодействия конечного устройства с ПК переплетается с описанием взаимодействия ПК с USB-хабом, функционал хаба мы не предусматриваем и не рассматриваем всё что его касается)
  5. Для контроля правильности передачи в каждом пакете предусмотрено поле CRC.
  6. Для кодирования данных в линии используется формат NRZI в котором постоянство логического уровня в линии соответствует единице, а изменение - нулю.
  7. Процесс передачи/получения данных выглядит следующим образом: хост посылает token с адресом устройства и указанием чего хочет - либо передать данные, либо принять их. В первом случае после token-а следует пакет с данными, после которого устройство должно ответить ASK в случае успеха или NAK в случае невозможности принять данные, ошибок CRC и пр. Во втором случае устройство само передаёт пакет данных и ожидает ASK от хоста, а с случае неудачи повторяет попытку.
  8. Процесс конфигурирования. ИМХО самая сложная стадия... Есть token-пакет типа SETUP. После него устройство должно ожидать пакета DATA0 в котором в поле данных особым образом сформирован запрос хоста (request), стандартные запросы описаны в секции Standart Device Request спецификации. Наше устройство должно уметь распознавать все типы запросов. Кроме прочего в запросе есть информация о том, куда должен быть направлен следующий пакет данных - в хост или в устройство.
  9. Более того, устройство должно уметь формировать ответ на запросы - должно сообщить хосту о своих свойствах через так называемые дескрипторы (Standart USB Descriptor). Полное их описание также довольно хорошо представлено в спецификации. Более того, именно этим разделам стоит уделить особое внимание. Отмечу лишь что через дескрипторы устройство сообщает свои Class, SubClass, Protocol, которые уже активно используются на уровне ОС и драйверов.

P.S. в дальнейшем тема обязательно будет продолжена, но уже с точки зрения железа и подготовки прошивки для МК.

понедельник, 18 февраля 2008 г.

Optical Spectrum Analyzer: сливаем данные

преамбула:

Приятно смотреть когда растёт материальная база научны лабораторий, появляются новые, современне приборы и пр, но как мы с ними работаем? Как правило для того чтобы хоть как-то проводить измерения зачастую можно даже не читать инструкции, и в единичных случаях это оправдано, ибо зачем читать толстую книжку, да ещё на английском, чтобы провести одно измерение... Другое дело, когда приходиться промерять некоторые зависимости, хотелось бы свести к минимуму рутинную и однообразную работу, тем более что приборы, о которых идёт речь, обладают множеством функций, скрытых от глаз обывателя.

удалённое управление:

Первый этап, сохранение графиков, с анализатора спектра на флеш. Прибор может быть подключён к компу посредством Ethernet, rs-232, GP-IB, остановимся на первом варианте (последний - пока экзотика, а ком-порта у меня на ноуте нет). К анализатору предлагается хороший мануал с описанием команд, которые можно посылать прибору через любой из этих интерфейсов. Таким образом задача сводиться к отправке команд в прибор,и в некоторых случаях, к анализу ответа. В качестве инструмента я остановился на python-е, погуглил как с его помощью работать с сетью, постаивл доки по стандартным функциям языка.

постановка задачи:

Чего хотелось бы прямо сразу:

  1. Скрипт, который по заданному шаблону формировал имена для файлов с крафикой и с данными. (для каждого типа - свой фиксированный префикс файла, основная часть имени задаётся пользователем)
  2. Сохранение графики и указанных спектров (в csv) на флеш (напрямую по сети можно получить лишь сырые csv, но с другой стороны есть простые команды для сохранения всего на флеш, т.е. нет необходимости заморачиваться ещё и обработкой, так что выбираем второй вариант)
  3. Файловые операции: переход в рабочую директорию или её создание, если таковой не существует, создание директории формата ггммдд для сохранения всех файлов.

решение:

На скорую руку в течении дня дня написал скрипт, который более-менее справляется с поставленной задачей. Написан он сейчас крайне не оптимально, контроль ошибок - минимальный, нет контроля от перезаписи файлов. Выложил файлик OSA_storage.py, вскоре причешу его и положу обновлённый вариант. Вскоре буду организовывать запись и сохранение нескольких участков спектра. Буду рад замечаниям и предложениям.