Знаковая проблема

Давно ничего не писал. А тут вдруг решил проблему, которая периодически занимала меня последний месяц. Речь про задачу про знаки из первой лабораторной работы курсеровского курса Hardware/Software Interface. Из-за этой задачи, я собственно и дропнул этот курс – не сумел решить с наскоку и расстроился.

Суть задачи в том, что используя только операции сложения, вычитания, умножения, битового сдвига влево и вправо, побитовых И, ИЛИ, НЕ, исключающего ИЛИ и оператора логического отрицания решить задачу нахождения знака 32-битного числа со знаком. На вход функции подаётся число, на выходе должны быть:

  • 1 – если число положительное
  • -1 – если число отрицательное
  • 0 – если число – это ноль

Использовать какие-либо операторы сравнения запрещено.

Задача решается элементарно благодаря оператору логического отрицания. Суть этого оператора в том, что он возвращает единицу, если ему на вход дали ноль и возвращает ноль, если на вход ему дали не ноль.

Фишка в том, что знак хранится в 31-ом бите и сам по себе выделяется очень просто. Засада на месяц состояла в том, чтобы отделить положительные числа от нуля – в обоих случаях в 31-ом бите сидит ноль. А решение состоит в том, чтобы умножить выделенный знак на двойное логическое отрицание исходного числа. Вот и весь фокус. Весьма тривиальный и простой, но непривычный для меня.

out = (1-2*((unsigned)in>>31))*!!in;

SCH/PCB муки

На меня несколько раз в год нападает желание найти замену P-CAD 2006, который,  как известно, умер, стух и сгнил. И раз за разом понимаю, что нету достойного соперника. Такое ощущение, что программисты кучи инженерно-девелоперских контор соревнуются в том насколько убогим и неюзабельным получится сделать своё программное обеспечение.

Сегодняшние претенденты: Cadence SPB и Zuken Cadstar.

1. Cadence SPB. На форуме Электроникса нашёл замечательную фразу от апологета данного программного продукта: “без тренинга новичок в данном продукте не сможет даже создать проект, не говоря уж о его дальнейшей разработке”. И это полная правда. На самом старте проекта приходится выбирать и компилировать какие-то стандартные-нестандартные библиотеки, писать в локальную библиотеку во внешнем текстовом редакторе какие-то слова и т.п. И это чтобы создать проект!

Ладно, предположим, что мы его таки создали, пользуясь туториалами. Открываем “Design Entry HDL” – штатную программу рисования электрической принципиальной схемы. Дизайн из конца восьмидесятых, кириллица в принципе не поддерживается, зато поддерживаются какие-то рюши, которые мне на данном этапе даром не нужны – всяческое моделирование и т.п. Нарисовал по туториалу схему, надо бы её транслировать в плату – а фигушки. Нету паттерна для выбранных микросхем. Я обычно рисую библиотеки полностью сам, но здесь я только начал разбираться с программой, и сплошное недоумение при виде кучи возникающих окон, мессаджбоксов с ошибками на голом месте. Мышкой ткнул в пустое место – получи мессаджбокс о том, что “какая-то команда не задана”. Вы серьёзно? Зачем использовать мессаджбоксы для некритических ошибок, уроды???

В общем, транслировать схему в плату так и не удалось пока. Буду еще ковырять, но уже видно, что по удобству работы оно на десять (если не на сто) голов ниже Пикада, который так любят хаять некоторые приверженцы этого поделия.

2. Zuken Cadstar. У этого программного продукта есть большое достоинство – наличие экспресс-версии с ограничением в 50 компонентов и 300 падов на проект. То есть маленькие платки и вообще научиться пользоваться можно совершенно легально, в отличие от.

Большой плюс видится в том, что программа по сути однооконная. А не куча малосвязанных между собой программ. Я, правда, уже вижу недостаток такого подхода в виде неудобства работы на двух мониторах, но пока не заостряю на этом внимание, т.к. может это и лечится.

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

Найденные проблемы в схемном вводе – не нашёл как скрывать атрибуты символа, отображение которых мне не требуется. На каждом символе в итоге куча лишних надписей. Рисование связей между элементами очень неудобное. В Пикаде даже не задумываешься об этом – щелкнул и повёл, как надо – так и провёл. Здесь же всё гораздо кривее и непонятнее. Но, возможно, это дело привычки.

Нарисовал схему, стал трассировать плату. При щелчке мыши на компоненте не факт, что выделится весь компонент, а не его часть. Может вылезти окошко с предложением выбрать что я хотел выбрать, но, в отличие от Пикада, курсор мыши не становится сам на первый элемент в списке. Лишние бесячие телодвижения. При разводке платы есть выбор между ручной разводкой, полуавтоматической, автоматической, автоматической для чипов памяти и “речной” разводкой. Нормально пользоваться можно только полностью ручной. В полуавтоматической и автоматической я так и не понял как заставить проводить проводники под углом в 45 градусов. Для чипов памяти не каждая цепь разводится, корреляции не нашёл пока. А речная тупо срезает путь – получается похоже на Топор.

Зукен Кадстар показался получше Каденс Аллегро в смысле юзабилити, но всё так же на десяток голов ниже Пикада. Явно видно, что разработчики пытались в некоторых местах копировать Пикад. Некоторые слямзенные идеи весьма удивляют своей недоделанностью – как с окошком выбора в разводчике.

Продукты Xilinx – трухлявая хрень!

Целый месяц бьюсь с отладочной платой ML510 от Xilinx. Такая лопата, внешне выглядящая как материнская плата ATX-формата. На борту – FPGA Virtex-5. Чем дальше я пытаюсь её заставить работать, тем больше она меня выбешивает!!!

Во-первых, это найденные баги:
1. В IP-ядре xps_tft, которое отвечает за коммуникации с чипом от Crontel и вообще за возможность работы с дисплеями по DVI какой-то криворучко забыл скобку поставить. Мне то пофиг, я исправил. Но вот КАК ОНИ ЭТО ТЕСТИРОВАЛИ??? Без скобки оно тупо не компилируется же!!!
2. В Xilinx Platform Studio раньше для выбора того куда присоединён порт был StringGrid с инкапсулированными ListDown’ами. Какому-то придурку это показалось некрасиво. Теперь там нужно щёлкнуть мышкой и появится уродливое мини-окошко, в котором надо выбрать выход с помощью того же ListDown’а. Стоит ли говорить, что механизм появления окошка по клику писал опять же криворучко? Я потратил сутки, чтобы понять, что окошко не появится в принципе, если XPS развёрнута на неосновном дисплее. Да-да, в Xilinx не знают, что многие пользуются несколькими мониторами одновременно!

Во-вторых. Платформа для написания кода для PowerPC 440, который встроен в тот Virtex-5 называется Xilinx SDK. Да щас! ЭТО ЭКЛИПС!!! Я его уже видеть не могу. Глючная среда, разработанная дизайнерами.

Неделю потратил на выяснение вопроса почему в ассемблере для PowerPC регистры называются r0,r1,..,r31, а ассемблер таких названий не понимает. Говорит “unsupported relocation against Rx”. Я вообще в принципе эту фразу не понимаю, что они хотели этим сказать?

Оказалось, что ему надо сказать, чтобы он такие названия понимал. Специальной директивой “-mregnames”. Причём, эту директиву надо задать не только ассемблеру, но и компилятору GCC (спрашивается, зачем си-компилятору директивы ассемблера?). Почему эта директива не выставляется автоматически – тоже тот еще вопрос. Видимо потому, что сами Xilinx’овцы своим поделием не пользуются. Во всяком случае мне трудно поверить, что они оперируют не названиями регистров, а адресами, где эти регистры находятся. Тут еще есть тот прикол, что, к примеру, SP (Stack Pointer – указатель стека) и регистр R1 – это одно и то же…

В эклипсе больше всего выбешивает запуск дебаг-сессии. Никогда не знаешь запустится она или нет. И не подаст ли она при старте полный хардверный ресет ПЛИСу, затирая сконфигурённый процессор, чтобы потом удивлённо так сказать окном на пол-экрана “А где же процессор?”.

Справедливости ради, один раз мне удалось пройти весь этот форт Боярд не уткнувшись ни в одну ошибку. И FreeRTOS у меня таки заработал. Но это было один раз, неделю назад. И второй раз повторить тот же путь у меня пока не получилось.

Индусы в Микросеми

На днях пришлось обратиться в техподдержку компании Микросеми. Проблема заключалась в следующем: нужно поставить СофтКонсоль – интегрированную среду разработки для программирования процессоров, входящих в системы-на-кристалле этой конторы – и софтовые, как Core8051s и встроенные АРМы. СофтКонсоль требует перед своей установкой обязательную установку утилиты программирования FlashPro версии не ниже 5.0. На официальном сайте даётся возможность скачать только последнюю версию этой утилиты – 10.0. Проблема заключается в том, что по-видимому проверяется только одна цифра перед точкой версии, и инсталлятор делает вывод, что установленная версия (10.0) гораздо меньше требуемой 5.0. Полный бред, с моей точки зрения. С этим и был послан запрос.

Пришёл ответ от господина с весьма показательной фамилией “Падала”. Он посоветовал установить целиком всю Libero SoC – приличного размера солянку из десятка разношёрстных утилит. Которые на той машине нафиг не сдались.

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

Где живёт uint32_t?

Начал писать заголовочные файлы для SmartFusion. Работа предполагается в SoftConsole. Есть несколько поименованных областей памяти, с которыми надо будет работать. Описаны они примерно следующим образом:

typedef struct
{
volatile uint32_t    TSW[16];
volatile uint32_t    SA[30][16];
}MKORX_TypeDef;

#define        MKORX_BASE        (0x40050000)
#define        MKORX            ((MKORX_TypeDef *) MKORX_BASE)

Дальнейшее использование, соответственно, стандартным образом: MKORX->SA[4][2] = 0xDEADBEEF;

Дык вот здесь есть малюсенькая такая тонкость, которая заключается в том, что тип uint32_t описан в файле stdint.h и его надо хотя бы единожды в проект включить. Иначе, возникает ошибка компилятора, которая в принципе не гуглится и по этому описанию понять – а в чём собственно ошибка? – не получится:

expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘TSW’

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

Лень и пыль

Дорешивал домашку к четвёртой неделе MITx 6.002x (да, дедлайн 8 апреля, а сегодня уже 7 – ну не было у меня возможности раньше заняться). И столкнулся с непонятностью.

По задаче нужно вычислить ток зависимого источника тока – мосфета, причём довольно хитро расположенного. Забудем про то, что ЭТО с моей точки зрения не цепь нифига – слева я имею ввиду. В смысле – ну там же разрыв!!! А вот с их точки зрения цепь. Потому что “воспользуйтесь законом Кирхгоффа о напряжении в контуре”. НУ ВЕДЬ НЕТУ КОНТУРА!!! Ладно, фиг с ними, предположим, что он есть. Едем дальше, загвоздка дальше. Ток мосфета вычисляется по формуле (K*(Vgs-Vt)^2)/2, где Vgs – напряжение, приложенное к затвору относительно истока, а Vt – напряжение срабатывания (threshold) (работаем мы типа в режиме сатурации насыщения!). Плюс надо вычислить напряжение Vout. Формула опять же по Кирхгоффу: Vout = Vdd-Rl*Id. Ток мы узнали на прошлом этапе, причём ток через транзистор вместе с резистором, поэтому нам резистор Rs второй раз учитывать не нужно.

Дык вот, решаю я квадратное уравнение. Получаю два корня, весьма близкие, но всё же. Выбираю меньший. Высчитываю по нему Vout. Ввожу оба ответа. И опаньки, Vout подходит, а Id, с помощью которого я Vout высчитал – нет. Ыыыы. Крыша едет.

Разгадка проблемы кроется в том, что я купил новые батарейки для своего инженерного калькулятора и когда менял их занёс под экран пылинку. Решив, что она мне и не мешает вовсе, я не стал разбирать калькулятор заново. А когда решал задачу эта пылинка мне обошлась привидевшейся точкой между целой и децимальной частью детерминанта. Разница между моим и правильным значением тока составила пятнадцать тысячных. Для расчета напряжения такая погрешность не вызвала проблем, а значение тока у меня не приняли…

H3P4 – как посчитать ток через идеальный диод

Какой-то несусветный ужас в домашней работе к третьей лекции. Схема в общем случае упрощается до такой: три параллельных плеча, первое – источник напряжения 7,5 вольт последовательно с резистором 5600 Ом, второе – источник напряжения 3.25 вольт последовательно с идеальным диодом, третье – нагрузочный резистор 5600 ом. Вопрос – какой ток будет течь через диод?
Первая мысль – диод идеален, сопротивление у него нуль, значит откидываем сопротивление нагрузки – туда ток не потечёт. И ответ тогда – бесконечность. Фигушки. Неправильная логика…

Два часа сражался с этой задачей. А оказалось всё просто – нарисовать эквивалентную цепь Тевенена и посчитать её. Дело тридцати секунд :(

Надо меньше думать привычными категориями и начинать пытаться использовать знания, которые даёт профессор Агарвал. Не зря ж он их даёт в конце концов…

Lab 2b

Задача такая. Есть два источника напряжения. Первый – меандр в диапазоне от 0 до 1 вольта. Второй – синусоида в диапазоне от -1 до 1 вольта. Надо получить из них сигнал V1/2+V2/6.
Вроде как всё просто – делитель на второй сигнал на три и затем сложить эти два сигнала – получится по половинке амплитуды от каждого. Но нужно при этом свести влияние делителя второго генератора на первый к минимуму. Тут всё зависит от того насколько нам это реально критично, т.е. какой ток мы собираемся с этого дела выбирать. Потому что если критично, то я бы тупо использовал операционные усилители – и дело с концом. Но здесь всё проще, так как про ток нам ничего не сказано. Ставим после делителя резистор на побольше, и последовательно с первым генератором резистор с таким же сопротивлением. И суммируем сигнал – получается верный ответ.

А теперь о проблемах. В обсуждениях на все вопросы об этой лабораторной очень часто разные люди загадочно говорят “не думайте, что двух резисторов достаточно, поставьте третий, не стесняйтесь”. Так вот, я не понимаю, как все эти люди добились правильного результата при помощи только трёх (не четырёх, как у меня) резисторов. Потому что резистор на общий провод в этом случае начинает делить результат после суммирования, а надо наоборот – сначала разделить, а лишь потом суммировать. Видимо я чего-то не догоняю…

MITx 6.002x

Наконец-то начался семестр в программе обучения MITx 6.002x. Очень интересно на какой по номеру неделе я брошу это занятие.

Первая же лабораторная работа заставила размять мозги. Хотя там по сути дела вообще нечего делать – посчитать резисторный делитель, удовлетворяющий некоторым условиям. Но вот пока не заставил себя не лениться и написать систему уравнений на бумажке и решить её – ответ не приходил. Это странно, учитывая, что у меня уже пятилетний стаж работы инженером и закон Ома применяется просто везде.

Загвоздка была в том, что видеть нагрузку делителя с небольшим сопротивлением в реальности приходится довольно редко в слаботочных цепях. То есть обычно мы пренебрегаем этим сопротивлением, считая его бесконечно большим, т.е. с бесконечно малым втекающим током. Плюс требование, чтобы резисторы в реальных цепях удовлетворяли в общем случае ряду E24 или в крайнем уж случае E96. Приходится перестроить мозг с реального мира на идеальный, т.к. ответ на первую лабораторную работу лежит вне этих рядов.

Далее нужно сделать домашнюю работу. Первое задание – сравнить количество энергии в БигМаке и батарейке для электромобиля. Вообще там могло быть всё что угодно, это задача тупо на арифметику первого класса. А вот дальше начинается уже ТОЭ. Придётся вспомнить законы Кирхгофа. На втором курсе они ну никак даваться не хотели, с тех пор я их позабыл, теперь придётся вспомнить. Третье задание – опять закон Ома, на этот раз нужно будет высчитать рассеиваемую мощность.

Интересно, когда мне надоест?

Android: Создание своих собственных визуальных элементов

Придумал себе новую андроидную задачку. Она включает в себя отрисовку нового, ни на что не похожего элемента управления и взаимодействие с ним.

Создадим свой собственный визуальный элемент управления. Делается это созданием нового класса, наследуемого от класса View.
Всё, что данный элемент управления должен отрисовать в себе делается в оверрайднутом методе onDraw, у которого в качестве параметра – канва. В этом методе самое главное – это в самом конце вызвать метод invalidate() – он даст знать Андроиду, что надо перерисовать канву. Если этот метод не вызвать, то чёрт его знает сколько придётся ждать пока Андроид решит, что данные устарели и принудительно перерисует наш элемент управления.

Предположим, что нам надо перерисовывать содержимое элемента управления в зависимости от того что пользователь навозюкал там внутри пальцем. За это отвечает метод onTouchEvent. Принимаемый им параметр event позволяет узнать всё, что пользователь делал с нашим контролом – как возюкал или тыкал и где конкретно он это делал.

Этих методов достаточно, чтобы контрол уже работал. Мы ставим наш контрол на лэйаут и далее у нас появляется задача как-то управлять этим контролом снаружи. Например, нам нужно знать координаты места где пользователь повозюкал пальцем. Метод, который мы описали ранее – это встроенный метод контрола, он не может никак повлиять на внешние для этого контрола вещи. Но мы можем создать в том классе статические глобальные (для класса) переменные и менять их из того метода, а уж доступ к этим переменным нам обеспечен – за счёт того, что они статические. Статические – значит они общие для нашего класса, а не создаются с каждым инстансом. Это не очень хороший стиль программирования с моей точки зрения, но если контрол в программе присутствует в единственном экземпляре – то почему бы и нет.

public class myNewView extends View
{

static int X; // Переменные, доступные снаружи
static int Y;

public myNewView(Context context, AttributeSet attrs)
{
super(context, attrs);
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
super.onTouchEvent(event); // очень важная строка, позволяет не только обработать
//касание здесь, но и при назначении метода onClick в
//Activity, инстантиировавшего наш
//контрол - обработать нажатие еще и там.
X=(int) event.getX(); // установка переменных для доступа к ним снаружи
Y=(int) event.getY();
return true;
}

@Override
protected void onDraw(Canvas canvas)
// метод OnDraw вызвается Андроидом тогда, когда нужно отрисовать данный View
{
// Здесь можно нарисовать всё что угодно на canvas
invalidate();// invalidate() нужен для того, чтобы оповестить Android,
//что нужно выполнить метод OnDraw снова, без него View не будет перериcовываться.
}
}