Аудиофилическое … или история моей болезни.

tidal

Вообще-то я считаю термин “аудиофил” оскорбительным. Это те самые люди, которые тащатся от слов “бескислородная медь” и покупают патч-корды за 500 баксов. В общем и целом вполне себе мирное заболевание, угрозы не несет никому, кроме кошелька его владельца, поэтому нормальные люди о нем практически ничего не знают.

Кто такие аудиофилы? Это люди, которые повернуты на качестве музыки, но при этом совершенно не разбирающиеся в том, на чем эту музыку играют. Именно для них sony выпустила специальную SD карту “для меломанов”, именно они спорят про разное звучание звука при смене кабелей на цифровых интерфейсах и так далее и тому подобное. Но при этом в “слепом тесте” они не могут отличить настоящий кабель от сделанного из вешалки.

Как отличить аудиофильскую тусовку или журнал от нормальных людей, жаждущих хорошего звука? Открываете любой обзор или тему и просматриваете наискосок. Если не увидели каких либо цифр и графиков, кроме стандартных “диапазон воспроизводимых частот” и “АЧХ”, а только слова про “кристальность звука” и “глубину звуковой панорамы” – это аудиофилы. Если пошли непонятные графики с пиками и терминами типа THD, SNR, SQ – то очень похоже, что это нормальные.

Можно подойти и с другой стороны. Аудиофилы не могут и не умеют оперировать объективными факторами, которые может подтвердить или опровергнуть измерительный прибор. Вся их основа сродне религии и опирается на “а я слышу!”.

В общем, вляпаетесь как я, разберетесь. А я вляпался довольно неожиданно для себя.

Давным давно, еще в начале этого тысячелетия, при “граблении” очередного диска я решил выяснить уровень, при котором я перестаю слышать разницу. Для этого я взял хорошо известный трек и начал “давить” его в разных форматах. Послушал его на компьютере, с колонками и наушниками. Перегнал на CD, оделся поприличней (что бы не посчитали за лоха) и сходил в один из пафосных салонов по продаже аудиоаппаратуры (в таких обязательно дают послушать покупаемое, даже со своих носителей). В результате походов я вывел четкое правило – “mp3, два прохода, VBR, средний битрейт 256” и все это время я подгонял коллекцию под это условие. Потом появился iTunes Store. Послушал их AAC, признал нормальным и дальше уже пополнял библиотеку им, тем более что я считаю iTunes лучшим каталогизатором музыки. Но не суть. Главное в том, что стандарты выработаны, библиотека собрана и в последнее время практически перестала пополняться – 60 тысяч треков мне в принципе хватило.

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

Стал слушать. Достал смартфон, закачал ту же песню, стал сравнивать. Звук разный! Ничего не понял. Подпробовал одно, другое … Не может же древняя звуковуха, да дешевые наушники ТАК влиять? Пошел на трекер, выкачал образ диска без потери качества и начал “передавливать” в разные битрейты.

Обнаружил, что я слышу разницу между 256 и 320. Но только на внешней звуковой. Но слышу. Опять не поверил. Пошел проверять.

Проверка простая: скачиваем foobar2000 и к нему расширение для слепого тестирование. Называется ABX Comparator. Два трека, слушаем, отмечаем, который думаем что лучше и потом смотрим. В общем, разберетесь, там просто.

Проверка показала: я 100% различаю 256 и 320 на знакомых мне мелодиях. Офигел мрачно. Включил FLAC. Различаю!

Ну, думаю “все, теперь пересобирать всю библиотеку во FLAC”. Расстроившись, полез смотреть, чем ее играют. Пока смотрел, наткнулся на тему про проигрывание многоканального звука. SACD, DTS, DVDA – эти буковки обычно про это. На пробу скачал какой-то альбом и попытался запустить на проигрывание. Почему попытался? Потому что в ответ услышал в колонках шум. Тут меня зацепило: у меня в колонках шум, а народ там хвалит вовсю. Разобрался, доставил декодеры. Заиграло … Ну вроде получше FLAC, а вроде и нет. Решил послушать на “большом” компьютере, к которому через встроенную звуковуху подключен девятилетний (в смысле старый, дешевый и из ДСП) комплект акустики 5.1.

И вот тут я обалдел. Это вообще совершенно иной звук. И это действительно надо слушать, ибо словами передать очень тяжело, потому что постоянно скатываюсь на междометия и правильных терминов не знаю. В результате я решил оставить вообще все задачи до завтра, расставил колонки и сел слушать с закрытыми глазами. И тут меня накрыло: я стал различать, где какой инструмент стоит и как соседи усаживаются поудобней (я скачал “живую” запись с какого-то концерта классической музыки). Обалдевший от прослушивания, решил прильнуть к “истокам”: альбом Майкла Джексона HiStory. 95й год, мой первый лицензионный диск, заслушанный до дыр на всех классах железок. Скачал пересведенную под DTS запись, включил и … попросту перестал удивляться. На досконально знакомой дорожке я услышал множество деталек, которые раньше не было слышно. Понимаете, их просто не было. Вообще.

Метнулся к компьютеру, начал на выборку выкачивать то один, то другой трек (благо интернет у меня быстрый) и в каждом обнаруживал что-то новое … Внутри меня стала расти волна предвкушения: представляете, 60 тысяч треков и все с чем-то новым? Ну или почти все, ибо я сомневаюсь что качество записей Высоцкого или Цоя будет отличаться.

Понапихал в трекер и стал разбираться, чем это играть. Если с большим компьютером проблем нет – там либо foobar2000, либо DeadBeeF и тему можно закрыть надолго, то с смартфоном и ноутбуком проблемы. Проблемы две: чем играть и чем слушать? С ноутбуком пока решил повременить: я смартфон слушаю чаще и дольше.

Почему я нашел проблему “чем играть”? Ведь в маркете этих плееров хоть ешь одним местом – выбирай любой. У этой проблемы аж два конца. Первый: разнообразие форматов и контейнеров. Где каждая песня отдельным файлом, где весь альбом в одной куче, а где вообще непонятно что. И это должно играться. Если с фубаром проблем нет, то с мобильными плеерами жопа. Декларируют много, а в реальности все зависят от возможностей одной и той же библиотеки.

Второй конец это сам андроид. До 5й версии андроиду было пофиг, какой звук и какого качества в него пихают – он его тупо перекодировал в 16бит на 44 килогерцах (В 5м обещают эту планку поднять) и только потом передавал наружу. Поэтому народ начал придумывать разные варианты. Скажу сразу, нормальных только два. Остальные – это улучшайзеры, которые умеют только играться эквалайзером и эффектами.

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

Второй способ – хаканье андроида с получением прямого доступа к железу. В моменте изучения данного вопроса для меня вскрылся очень интересный факт: в топовые модели обычно вставляют и топовые чипы, в том числе и аудио. То, что их никто и ничего использовать не может – никого не волнует: маркетолухи отчитались, хомячки впечатлились и напокупали. В данном способе есть пара очередных проблем: производители вовсе не горят желанием давать доступ до внутренностей телефона и у некоторых моделей попросту нет отдельного звукового чипа.

После “всплывания” из глубин интернета появилась и еще одна проблема: качество разных реализаций декодеров тоже было разным. Одна проблема тащит за собой другую …

Походы по форумам выявили двух претендентов на звание “музыкальный плеер”: USB Audio Player PRO и Neutron. Оба стоят в районе 300 рублей, оба собрали кучу положительных отзывов на профильных форумах.

Ставлю первый. Играет. Достаю usb-otg кабель и подключаю через него SoundBlaster. Играет. С заморочками типа “сначала подключите карточку, а только потом запускайте плеер”, но играет. Ок.

Ставлю второй. Играет. Как использовать внешнюю карточку не понял, но играет. Потыкал всякие аудиофильские галочки типа “наплевать на процессор, считай все в 64х битах”. Заиграл еще лучше. Основной минус – совершенно уе…щный интерфейс. Автор (кстати наш, русскоговорящий) откровенно забил на дружелюбность к пользователям. Все, что не относится к звуку – начхать. Поэтому забудьте про плейлисты и прочие прибамбасы типа выбора откуда играть будем. Они официально есть, но не работают. Но играет хорошо, собака серая.

neutron

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

Опять на форумы. Мой нынешний Lenovo P70 хакать смысла особого нет: весь звук на одном чипе с процессором. Что там – фиг его знает. Через кучу времени выбора моего будущего смартфона наткнулся на немного ностальгический пост про то, какой же клевым был Samsung Galaxy S и каким гавном оказался шестой. Звуковой чип Wolfson 8994, топовый для 2010 года … Оппа! А у меня валяется мой старый SGS. И даже в рамках ТО я недавно заряжал ему аккумулятор – вполне живой.

Сначала заливаю туда тестовые треки. Слушаю. Ну в принципе неплохо, но P70 играет лучше. И довольно сильно лучше так – сказываются 5 лет разницы. Заливаю туда последний цианоген, попутно снося все накопленное непосильным трудом, включаю все галочки …

DSP

Нахожу более-менее приличное и вижу зажегшуюся иконку. Жамкаю на play … едреныть! Как он оказывается умеет играть! Одни писки, визги и междометия от меня.

В результате я получил дешевый аудиофильский плеер. Да, он тормозит, да он не выглядит гламурно и стоит копейки. Но зато 24 бита, 96kHz и 100dB SNR вместе с усилителем D/AB.

И тут я остановился. Любой шаг в сторону улучшения звука теперь для меня будет стоить денег. Нет, куда двигаться понятно и так: сначала хорошие наушники на замену моим CX-300II, а затем внешний DAC. Но вот насколько широким должен быть шаг ….

Программируем микроконтроллеры в QtCreator

Это копия моей статьи, опубликованной на хабре

qbs03
Почему-то в интернете мало документации про qbs, пора немного исправить эту ситуацию.

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

Но поверьте, это довольно быстро задалбывает. Под виндовс – MSVC, под ARM – CooCox или Keil (приношу свои соболезнования вынужденным работать под IAR), под MSP – CCS, под андроид – eclipse, под ios – Xcode, под пики – MPLAB. И ладно бы, со всем этим работать можно было бы, но ведь фиг: везде свои заморочки, тонкости и неписанные правила. Все это накладывается на общую тормознутость так популярного эклипса помноженную на криворукие дополнения от производителей.

Некоторое время назад я начал сводить все свои разработки под мобильные и десктопные приложения под одну платформу. После довольно долгого чеса по интернетикам мой выбор остановился на Qt. Есть все, что надо, при необходимости можно подцепить нативный код. В общем, задача закрылась.

Но вот с микроконтроллерами ситуация не желала складываться категорически. В основном из-за того, что везде свои хотелки и желалки. Ну ладно, про это я уже жаловался. Я бы еще долго мучался, пока внезапно не наткнулся на краткое описание qbs.

Желающие могут пошариться по инету сами, но если кратко, то это заменитель всяких make и cmake, использующая нормальный (тут должен быть смаил) язык программирования. И сам QtCreator собирается с ее помощью, значит она уже вылезла из штанишек …

Да, документации по ней как обычно кот наплакал, но исходники еще никто не отменял, поэтому довольно быстро ко мне пришло понимание, что это практически то, что я искал. Посудите сами: сидишь в одной среде разработки (самой по себе очень приятной и быстрой) и спокойно пишешь и редактируешь файлы под несколько платформ. И тебе, как кодописателю, пофиг на наличие всяких там заморочек с “родными” средами.

Хватит излияний, пора попробовать. Создадим очень простой проект, в котором у нас будет десктопная и микроконтроллерная составляющая.

Открываем QtCreator, выбираем создать Non-Qt Project (что бы пока не заморачиваться сильно) и далее выбираем то, где присутствует C и Qbs. Обратите внимание на приятные взгляду слова Platform independent

qbs01

В результате получаем один main.c и qbs. Можно уже нажать “build” и получить вывод Hello World.

Открываем qbs и ничего не понимаем. Поэтому все стираем, вооружаемся интернетом и начинаем писать. Яваскрипт и все такое.

import qbs

Так, тут вроде понятно. Импортируем всякое необходимое для работы самого qbs.

Project {
name: "simple"
}

Сохраняем и наблюдаем исчезновение main.c с левой панели. При попытке запустить проект QtCreator спросит: а чего пускать-то? В принципе пока все логично.

Из чего состоит проект в терминологии qbs? Из продуктов. И их может быть несколько, но пока я сделаю один.

Project {
name: "simple"
Product {
name: "desktop"
}
}

Теперь для нашего “десктопного” укажем исходник.

Project {
name: "simple"
Product {
name: "desktop"
files: "main.c"
}
}

При попытке скомпилировать не изменится ровным счетом ничего. Подсмотрим в некоторые обучалки и добавим зависимость от cpp и укажем, что вообще-то это приложение.

Project {
name: "simple"
Product {
name: "desktop"
files: "main.c"
Depends {name: "cpp"}
type: "application"
}
}

И вот теперь при попытке собрать приложение QtCreator пошуршит немного диском и в панельке Application Output появится искомое

qbs02

Ага, значит мы на верном пути. Осталось разобраться, что делают те самые две магические строки.

Depends {name: "cpp"}

Читаю документацию и понимаю, что данной командой я устанавливаю зависимость проекта от какого-то модуля с именем cpp. Понятней стало? Мне нет.

Простым поиском нахожу что-то подобное в /usr/share/qtcreator/qbs/share/qbs/modules/ (Если у вас другая операционка, то скорее всего аналогичное лежит где-то неподалеку от QtCreator). Если говорить коротко, то там куча яваскрипта, которая в зависимости от платформы подбирает компилятор под эту платформу. Полностью повторять подобное мне смысла нет, поэтому оставляю как есть.

type: "application". Из документации: The file tags matching the product’s target artifacts. Артефакт … An Artifact represents a single file produced by a Rule or Transformer. … ерр .. Rule? Creates transformers for input tags. Напоминает ситуацию про сепулькарий .. Transformer? Creates files, typically from other files.

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

Но вернемся к нашему проекту. Давайте добавим еще один продукт, только уже для микроконтроллера

Project {
name: "simple"
Product {
name: "desktop"
files: "main.c"
Depends {name: "cpp"}
type: "application"
}
Product {
name: "micro"
files: "blink.c"
}
}

При попытке что-то сделать, нам сразу выскочит сообщение, что вообще-то файла blink.c нет. Ну, ок, добавим в проект фаил blink.c. Как видно из названия, это тот же HelloWorld, только для микроконтроллеров. Я взял из примеров для микроконтроллера семейства msp430.

#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD;
P1DIR |= 0x01;

while (1) {
P1OUT ^= 0x01;
__delay_cycles(1000000); // 1 second @ 1MHz
}

return 0;
}

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

Теперь QtCreator не ругается, но и в микроконтроллер ничего не заливается. Странно, да?

Добавлять Depends {name: “cpp”} смысла нет, потому что установленный в системе родной gcc не в курсе про существование такой платформы, да и в дальнейшем пригодится, например для пиковских контроллеров, где вообще все свое.

Теперь воспользуемся обрывками тех сакральных буковок, что встретились раньше.

Для начала, я предпочитаю в микроконтроллерных проектах расписывать каждый функционал в своем файле. Записывать каждый файл руками? Лень. Подсматриваем решение и переписываем блок

Product {
name: "micro"
Group {
name: "msp430 sources"
files: 'src/*.c'
fileTags: ['c']
}
}

Тут создаем группу файлов, которые обзываем “msp430 sources” и тупо включаем в нее все файлы, которые подходят под маску src/*.c. Для дальнейшей работы с ними тегируем их буквой С.

Что с ними делать? У qbs есть на этот случай две штуки – Rule и Transformer. По сути они близки, но немного разные. Счас попробую описать на пальцах разницу.

Rule умеет срабатывать на каждый файл, попадающий под что-то. Может срабатывать по разу на каждый фаил (например, для вызова компилятора), а может один раз на все (линкер).

Transformer предназначен для срабатывания только на один фаил, с заранее определенным именем. Например, прошивальщик или какой-нибудь хитрый скрипт.

Ок, добавляем правило, которое должно будет сработать на все наши файлы, промаркированные как “с”.

Product {
name: "micro"
Group {
name: "msp430 sources"
files: 'src/*.c'
fileTags: ['c']
}
Rule {
inputs: ["c"]
prepare: {
var cmd = new JavaScriptCommand();
cmd.description = "file passing"
cmd.silent = false;
cmd.highlight = "compiler";
cmd.sourceCode = function() {
print("Nothing to do");
};
return cmd;
}
}
}

В принципе из синтаксиса уже все понятно. Есть inputs, есть prepare, в который засовывается яваскрипт, который выполняет необходимое. В данном случае он должен в окошке Compile Output показать file passing, и куда-то вывести Nothing to do. Ну по документации вроде так.

Запускаем перекомпиляцию всего и смотрим. Не знаю, как у вас, но я ничего не вижу. Почему? Потому что qbs больно умный, а документация к нему страдает лакунами.

Правило не срабатывает, потому что qbs считает, что оно не производит никаких действий в системе и от него ничего не зависит. В принципе это соответвует реальности, но провести проверку мешает.

Ок, за это отвечают те самые артефакты. Под ними подразумеваются результаты деятельности Rule или Transformer. Лучше всего это объяснить на примере компиляции. Когда мы компилируем .с файл, то на выходе мы получим объектный файл .о. Он нам нужен для дальнейшей линковки, но с другой стороны, мы его можем удалить, так как потом спокойно сможем сгенерировать заново.

Опять копируем пример из документации и чуть-чуть модернизируем.

Rule {
inputs: ["c"]
Artifact {
fileTags: ['obj']
filePath: '.obj/' + qbs.getHash(input.baseDir) + '/' + input.fileName + '.o'
}
prepare: {
var cmd = new JavaScriptCommand();
cmd.description = "Compiling "+ input.fileName
cmd.silent = false;
cmd.highlight = "compiler";
cmd.sourceCode = function() {
print("Nothing to do");
};
return cmd;
}
}

Теперь мы говорим, что после нашей деятельности останутся артефакты в каталоге .obj (ну и я добавил вывод того, над каким файлом мы сейчас работаем). Запускаем. Опять ничего в ответ. Почему? Ответ тот же – никому не нужны файлы с тегом ‘obj’.

Хорошо, для проверки сделаем так, что они нужны нам. И вообще, наше приложение – это один сплошной obj.

Product {
name: "micro"
type: "obj"
Group {
name: "msp430 sources"
files: 'src/*.c'
fileTags: ['c']
}
Rule {
inputs: ["c"]
Artifact {
fileTags: ['obj']
filePath: '.obj/' + qbs.getHash(input.baseDir) + '/' + input.fileName + '.o'
}
prepare: {
var cmd = new JavaScriptCommand();
cmd.description = "Compiling "+ input.fileName
cmd.silent = false;
cmd.highlight = "compiler";
cmd.sourceCode = function() {
print("Nothing to do");
};
return cmd;
}
}
}

Пробуем, и удача! В окошке появился заветный “Compiling blink.c”. Теперь давайте добавим, что бы оно реально компилировало и сразу по-быдлокодерски, то есть тупо забив все необходимое в одну кучу.

prepare: {
var args = [];
args.push("-mmcu=cc430f5137")
args.push("-g")
args.push("-Os")
args.push("-Wall")
args.push("-Wunused")
args.push('-c');
args.push(input.filePath);
args.push('-o');
args.push(output.filePath);
var compilerPath = "/usr/bin/msp430-elf-gcc"
var cmd = new Command(compilerPath, args);
cmd.description = 'compiling ' + input.fileName;
cmd.highlight = 'compiler';
return cmd;
}

Перекомпилируем все с нуля и смотрим в каталог .obj

$ ls -R1
.:
f27fede2220bcd32

./f27fede2220bcd32:
blink.c.o

Ура! Файлик появился. Теперь, для проверки я делаю еще один файлик, с хитрым названием hz.с. Если я прав, то после перекомпиляции рядом появится еще один объектный файл.

В выводе появилось

compiling blink.c
compiling hz.c

а в каталоге

./f27fede2220bcd32:
blink.c.o
hz.c.o

Все вроде ок. Теперь необходимо все это дело слинковать. А значит опять правило, только теперь для линковки.

Rule {
multiplex: true
inputs: ['obj']
Artifact {
fileTags: ['elf']
filePath: project.name + '.elf'
}
prepare: {
var args = [];
args.push("-mmcu=cc430f5137")

for (i in inputs["obj"])
args.push(inputs["obj"][i].filePath);

args.push('-o');
args.push(output.filePath);
var compilerPath = "/usr/bin/msp430-elf-gcc"
var cmd = new Command(compilerPath, args);
cmd.description = 'linking ' + project.name;
cmd.highlight = 'linker';
return cmd;
}
}

Где отличия? Во-первых, добавился флаг multiplex, который говорит о том, что это правило обрабатывает сразу все файлы данного типа скопом. А во-вторых, во входных параметрах исчез input. Появился inputs, который является массивом файлов данного типа. Ну и я вопользовался именем продукта, что бы брать имя для финальной прошивки.

Ставим тип приложения elf и пробуем собрать. Через некотрое время мы в каталоге для сборки обнаружим файл simple.elf

$ file simple.elf
simple.elf: ELF 32-bit LSB executable, TI msp430, version 1, statically linked, not stripped

То, что нам и необходимо. Его можно уже заливать в плату и наслаждаться мигающим светодиодиком.

Исходная цель достигнута: мы в одной среде разработки делаем все: и редактирование и компиляцию.

На всякий случай конечный qbs

import qbs
Project {
name: "simple"
Product {
name: "desktop"
files: "main.c"
Depends {name: "cpp"}
type: "application"
}
Product {
name: "micro"
type: "elf"
Group {
name: "msp430 sources"
files: 'src/*.c'
fileTags: ['c']
}
Rule {
inputs: ["c"]
Artifact {
fileTags: ['obj']
filePath: '.obj/' + qbs.getHash(input.baseDir) + '/' + input.fileName + '.o'
}
prepare: {
var args = [];
args.push("-mmcu=cc430f5137")
args.push("-g")
args.push("-Os")
args.push("-Wall")
args.push("-Wunused")
args.push('-c');
args.push(input.filePath);
args.push('-o');
args.push(output.filePath);
var compilerPath = "/usr/bin/msp430-elf-gcc"
var cmd = new Command(compilerPath, args);
cmd.description = 'compiling ' + input.fileName;
cmd.highlight = 'compiler';
return cmd;
}
}
Rule {
multiplex: true
inputs: ['obj']
Artifact {
fileTags: ['elf']
filePath: project.name + '.elf'
}
prepare: {
var args = [];
args.push("-mmcu=cc430f5137")

for (i in inputs["obj"])
args.push(inputs["obj"][i].filePath);

args.push('-o');
args.push(output.filePath);
var compilerPath = "/usr/bin/msp430-elf-gcc"
var cmd = new Command(compilerPath, args);
cmd.description = 'linking ' + project.name;
cmd.highlight = 'linker';
return cmd;
}
}
}
}

PS Вынос “захардкоденных” переменных в более удобное место оставлю на вашей совести, ибо это уже к обучалке по яваскрипту.

Lenovo P70

В принципе, после пары месяцев владения уже можно описать свои впечатления от агрегата. Всякие “что внутри” легко можно найти в сети, поэтому повторяться не буду, только личные впечатления.

Итак, для начала о плохом. Внутри android 4.4.4. У самого андроида только одна проблема – кривой часовой пояс. Поэтому время звонков и смсок сдвинуто на час вперед. К сожалению, нормально лечится только рутованием аппарата, поэтому забил.

К самой оболочке есть только одна претензия – на всякие выпенждрежные штуки типа включения-выключения по расписанию разработчики забили. То есть оно может сработать, а может и не сработать. Но так как это именно выпендрежная штука, то никаких проблем она не доставляет.

В остальном вроде проблем нет. Все ставится, все работает … Кстати, работает очень долго. Как и предидущая модель, позволяет заряжаться не тогда, когда надо, а тогда, когда есть время. А если зарядиться забыл, то до вечера он дотянет без каких-либо проблем.

Screenshot_2015-04-01-17-18-18

Этот график я снял в первые дни владения телефоном. Никаких заморочек типа “замораживания” или выключения беспроводных сетей не делалось. Владельцы модных самсунгов и айфонов нервно завидуют.

MSP430 и Fedora Linux

В принципе, в программировании микроконтроллеров под Linux нет ничего сложного. Более-менее доступны средства разработки, а некоторые производители и вовсе официально поддерживают Linux как среду разработки.

TI тоже имеет свою фирменную среду, но она … скажем так, для хардкорных железячников. Старый, тормознутый эклипс и какие-то невнятные настройки. Залитие прошивки и ее отладка тоже доставляют много удовольствия привыкшим к нормальным средам.

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

Расписывать я буду под Fedora Linux (21), потому что я сейчас под ней. Под другие дистрибутивы инструкций как-то больше.

В чем проблема с федорой? Ведь они кровь и плоть от редхата, а тот официально поддерживает msp430-gcc, который использует и сама TI. Проблема в том, что это федора, а значит в ней все нестабильное и вообще может не работать.

И с MSP430 случилось ЭТО. В 20й версии он работал, а в 21й – уже нет. Подробнее можно посмотреть тут. Если кратко, то в федоре сломали линкер.

Что делать? Есть несколько вариантов, из которых самый простой это взять старую версию компилятора из CCS или Energia. Но добрый Brandon Nielsen решил эту проблему по-другому: просто сделал репозиторий со правильными версиями.

Открываем рутовую консоль и подключаем нужный репозитарий

dnf copr enable nielsenb/msp430-development-tools

И ставим все необходимое, соглашаясь с тем, что никто ни за что не отвечает.

yum install msp430-elf-gcc msp430-elf-binutils msp430-elf-gdb mspds msp430flasher msp430-gcc-support-files dos2unix srecord

Теперь скопипастим Makefile
#
# Makefile for msp430
#
# 'make' builds everything
# 'make clean' deletes everything except source files and Makefile
# 'make install' builds everything, and programs the MSP430 using MSPFLASHER
# You need to set TARGET, MCU and SOURCES for your project.
# TARGET is the name of the executable file to be produced
# $(TARGET).elf $(TARGET).hex and $(TARGET).txt nad $(TARGET).map are all generated.
# The TXT file is used for BSL loading, the ELF can be used for JTAG use
#
TARGET = project0
MCU = msp430f5529
# MSP430Flasher name
MSPFLASHER = MSP430Flasher
# List all the source files here
# eg if you have a source file foo.c then list it here
SOURCES = main.c delay.c
# Include are located in the Include directory
INCLUDES = -IInclude
# Add or subtract whatever MSPGCC flags you want. There are plenty more
#######################################################################################
CFLAGS = -mmcu=$(MCU) -g -Os -Wall -Wunused $(INCLUDES)
ASFLAGS = -mmcu=$(MCU) -x assembler-with-cpp -Wa,-gstabs
LDFLAGS = -mmcu=$(MCU) -Wl,-Map=$(TARGET).map
########################################################################################
CC = msp430-elf-gcc
LD = msp430-elf-ld
AR = msp430-elf-ar
AS = msp430-elf-gcc
NM = msp430-elf-nm
OBJCOPY = msp430-elf-objcopy
RANLIB = msp430-elf-ranlib
STRIP = msp430-elf-strip
SIZE = msp430-elf-size
READELF = msp430-elf-readelf
MAKETXT = srec_cat
CP = cp -p
RM = rm -f
MV = mv
########################################################################################
# the file which will include dependencies
DEPEND = $(SOURCES:.c=.d)
# all the object files
OBJECTS = $(SOURCES:.c=.o)
all: $(TARGET).elf $(TARGET).hex $(TARGET).txt
$(TARGET).elf: $(OBJECTS)
echo "Linking $@"
$(CC) $(OBJECTS) $(LDFLAGS) $(LIBS) -o $@
echo
echo ">>>> Size of Firmware <<<<" $(SIZE) $(TARGET).elf echo %.hex: %.elf $(OBJCOPY) -O ihex $< $@ %.txt: %.hex $(MAKETXT) -O $@ -TITXT $< -I unix2dos $(TARGET).txt # The above line is required for the DOS based TI BSL tool to be able to read the txt file generated from linux/unix systems. %.o: %.c echo "Compiling $<" $(CC) -c $(CFLAGS) -o $@ $< # rule for making assembler source listing, to see the code %.lst: %.c $(CC) -c $(ASFLAGS) -Wa,-anlhd $< > $@
# include the dependencies unless we're going to clean, then forget about them.
ifneq ($(MAKECMDGOALS), clean)
-include $(DEPEND)
endif
# dependencies file
# includes also considered, since some of these are our own
# (otherwise use -MM instead of -M)
%.d: %.c
echo "Generating dependencies $@ from $<" $(CC) -M ${CFLAGS} $< >$@
.SILENT:
.PHONY: clean
clean:
-$(RM) $(OBJECTS)
-$(RM) $(TARGET).*
-$(RM) $(SOURCES:.c=.lst)
-$(RM) $(DEPEND)
install: $(TARGET).txt
$(MSPFLASHER) -n $(MCU) -w "$(TARGET).txt" -v -z [VCC]

Если при попытке компиляции Вы получите

Makefile:48: *** missing separator. Stop.

то это означает лишь то, что вы нарвались на tab-hell. Все отступы выше – это не пробелы, а символы табуляции. Если отвлечься и открыть этот фаил в mc, то вы должны увидеть следующее:

mc_tab

Обратите внимание на символы “<---->” – именно ими mc показывает табуляцию. Поправьте где надо.

Теперь осталось поправить параметры MCU под мой процессор и SOURCES под мой проект и запустить make. Если все сделано правильно, то вы должны увидеть побежавшие строки, завершающиеся чем-то похожим.

Linking blink.elf

>>>> Size of Firmware <<<< text data bss dec hex filename 2906 214 152 3272 cc8 blink.elf unix2dos: converting file blink.txt to DOS format...

Если оно так, то можете себя поздравить. Теперь можно развиваться дальше.

PS С автором, чьи наработки я использовал, можно познакомиться тут