Fun Electronic

Электронные поделки, программирование микроконтроллеров, и прочая белиберда|Electronic Basteleien, Mikrokontroller Programmierung und anderes Quatsch

RSS
people

Mazda MP3 Player — Продолжение 3|Mazda MP3 Player — Dritte Folge

[lang_ru]А вот и снова я![/lang_ru]

[lang_de]Ich bin wieder da! [/lang_de]

[lang_ru]Надеюсь, не заскучали тут без меня?[/lang_ru]

[lang_de]Hoffe, dass ihr hier nicht gelangweilt ohne mich? [/lang_de]

[lang_ru]У меня есть уважительная причина — я отлавливал баги в софте плеера. И довольно таки много отловил.[/lang_ru]

[lang_de]Ich habe aber eine Ausrede. Ich habe die Bugs in meinem Player gesucht. Und muss man sagen, ganz erfolgreich.  [/lang_de]

[lang_ru]В прошивке ПЛИС от Xlilinx заменил модуль выбора банков памяти на VHDL аналог, написанный с учетом всех особенностей адресации памяти и схемы.[/lang_ru]

[lang_de]In der CPLD Firmware habe ich den Modul zum Selectieren des Memory-Banks mit einem VHDL-Analog ersetzt.[/lang_de]

[lang_ru]В софте, соответственно, сделал изменения в системе Кучи (Heap), так как она напрямую связана с адресацией внешней памяти.[/lang_ru]

[lang_de]In der Player-Firmware habe einige Änderungen in Heap-System gemacht, da das System hängt direkt von Memory-Banken.  [/lang_de]

[lang_ru]Теперь у меня используются все банки памяти.[/lang_ru]

[lang_de]Jetzt werden alle Memory-Banken benutzt. [/lang_de]

[lang_ru]Нашелся старый баг, заложенный мною же пару лет назад по тогдашней неопытности — в системе проигрывания MP3 файла использовался один из банков, и так как в то время я еще не совсем знал, на что мне потратить такое количество банков (30 штук), то я выбрал второй, с номером 1 (нумерация идет с 0, как мы помним). И вот он сейчас вылез боком, когда банк с этим номером использовался так же для хранения технической информации о всех файлах, найденных при сканировании дисков.[/lang_ru]

[lang_de]Es wurde alete Bug gefunden, der ich selber reinprogrammiert habe, weil ich noch jung und unerfahren war. In dem MP3-Datei-Abspiel-System wurde ein der Memory-Banken benutzt. Und damals wusste ich noch nicht, wofür ich so viel speicher brauchen kann (30 Stuck), habe ich mich den 2. augesucht, und hard kodiert. Und jetzt ist das aufgetaut, weil dieser Bank wird für Technikal Info aller Dateien benutzt. [/lang_de]

[lang_ru]Система работала до первого проигрывания файла, играла первый файл хорошо, но при попытке выбора следующего — зависала и перезагружалась Вачдогом.[/lang_ru]

[lang_de]Das System funktionierte bis ertste Abspielvorgang der MP3-Dateien. Wenn man aber versucht, die nächste Datei zu wählen, hängte das System und resetete sich durch Watchdog. [/lang_de]

[lang_ru]А не находился этот баг так долго потому, что я, по тогдашней неопытности, сделал выбор банка в обход интерфейса управления банками памяти, напрямую записывая в регистр банка его номер. Вот нам и урок на будущее — организовывайте доступ к какому либо модулю посредством интерфейса, и используйте только его![/lang_ru]

[lang_ru]В самом софте пока что сменил команды доступа к дисками с простых присваиваний на свои функции, которые пишут и читают не черех интерфейс внешней памяти контроллера, а путем прямого управления портами PORTA, PORTC и пинами N_RD, N_WR и ALE. На такой шаг замедления процесса чтения я пошел из-за того, что текущая прошивка CPLD немного подтормаживает при обработке адреса, и с момента выставления сигналов N_RD или N_WR проходит около 100 наносекунд, что очень много, так как нам надо успеть еще установить сигналы выбора дисков, немного подождать и потом установить сигналы чтения дисков. Если между этим двумя событиями не ждать, то что диск, что карточка, нас не поймут, и мы ничего не считаем с них. Временные параметры надо выдерживать.[/lang_ru]

[lang_de]In der Firmware wurde die Kommandos des Zugrifes zu den Festplaten von einfachen Zuweisungen auf die Funktionen ersätzt, die schreiben und lesen die Daten nicht über den external Memory-Interface, sonder über GPIO zugrife über Ports PORTA, PORTC und Pins N_RD, N_WR und ALE. Diese Bremse habe ich deswegen eingebaut, weil jetzige CPLD-Firmware ist ein bisschen langsam bei der Abarbeitung der Adresse. Und ab dem Zeitpunkt als die N_RD, bzw. N_WR Pins gesetzt werden, braucht man ca. 100 Nanosekunden, bis alles Signale durch CPLD von Mukro zu die Festplatte durchkommen. Und Mikro ist schon am Ende des Lese/Schreib Zyklus, aber Festplatte fängt erst an zu reagieren. Also, CPLD ist ein bisschen langsam im Moment.  [/lang_de]

[lang_ru]Так вот. Пока мы это все выставляем тут и ждем, процессор нифига не ждет, надо сказать. И соответсвенно, ничего не считывает, или же очень малый процент считываний проходит успешно. На жестком диске это все как то еще работало, а вот карточка уже не успевала. И это была еще HS карточка, т.е высокоскоростная. А я попробовал поставить карточку помедленней — так ее даже не распознал плеер. Т.е. вообще никакой инфы не считалось.[/lang_ru]

[lang_ru]По этому я пока что заменил обычные присваивания (которые процессор направляет на интерфейс внешней памяти) на процедуры прямого управления портами. Хоть и медленно, но работает все как часики. И все карточки и жесткий диск прекрасно считываются.[/lang_ru]

[lang_de]Deswegen habe ich die einfache Zuweisungen auf external Memory-Interface durch langsame Funktionen ersätzt. Ist zwahr langsamer geworden aber funktioniert. [/lang_de]

[lang_ru]Но я, естественно, собираюсь оптимизировать прошивку cpld, не без помощи своего друга из Москвы, McSim, что бы увеличить скорость. А то уж больно медленно получается, чем было до этого.[/lang_ru]

[lang_de]Ich bi aber dabei die CPLD-Firmware zu modificieren, damit die schneller arbeitet. [/lang_de]

[lang_ru]А пока, как и обещал в прошлый раз, поговорим о методах работы с шиной M-Bus. О том, как считывать даный из нее, и как в нее писать что-либо.[/lang_ru]

[lang_de]Und jetzt reden wir über die M-Bus. Wie man die Daten davon rausliest, oder die dort reinschreibt. [/lang_de]

[lang_ru]Процессы чтения шины и записи в нее управляются посредством перерываний. Для чтения мы используем внешнее прерывание от ноги процессора, на которую предварительно завели сигнал с шины. А для записи — используем таймер.[/lang_ru]

[lang_de]Lesevorgang ist über external Interrupt realisiert. Und zum Schreiben wird ein Timer benutzt.   [/lang_de]

[lang_ru]Процесс чтения начинается по прерыванию по падающему фронту:[/lang_ru]

[lang_de]Leseforgang fängt bei fallende Flanke des pins. [/lang_de]

[codesyntax lang="c" lines_start="182" container="div" title="Receive Interrupt" ]

/*
 *   Receive interrupt
 */
SIGNAL(MBUS_RX_SIG_INT)
{
  u08 register bTimerVal;
  if ( MBRProcess.bCanReceive )
  {
    switch ( MBRProcess.bBitRecState )
    {
      default:
      case  MBR_WAITING:
        if ( MBTProcess.bSending == 0 )
        {
          MBRProcess.bBitCounter = 0;
          MBRProcess.bBitRecState++;
        }
      case MBR_FALLING:

        MBUS_RX_TCNT        = 0;
        MBUS_RX_TIMER_TCCR  = MBUS_RX_PRESCALE;                       

        MBUS_RX_EICR &= ~MBUS_RX_INT_MSK;
        MBUS_RX_EICR |=  MBUS_RX_INT_RIS;
        MBRProcess.bBitRecState++;
      break;

      case MBR_RISING:
        bTimerVal = MBUS_RX_TCNT;

        MBRProcess.bBitsArray[ MBRProcess.bBitCounter / 8 ] &= ~(1 << ( 7 - (MBRProcess.bBitCounter % 8) ) );
        if (
             ( bTimerVal >= ( MBUS_TCNT_LOW_ONE - MBUS_TCNT_TOLERANCE ) ) &&
             ( bTimerVal <= ( MBUS_TCNT_LOW_ONE + MBUS_TCNT_TOLERANCE ) )
           )
        {
          MBRProcess.bBitsArray[ MBRProcess.bBitCounter / 8 ] |= (1 << ( 7 - (MBRProcess.bBitCounter % 8) ) );
        }

        MBRProcess.bBitCounter++;                                     

        MBUS_RX_EICR &= ~MBUS_RX_INT_MSK;
        MBUS_RX_EICR |=  MBUS_RX_INT_FAL;
        MBRProcess.bBitRecState = MBR_FALLING;                        

        SWTLoad(SWT_MBUS_PACKET_TIMER, SWT_MBUS_PACKET_TIMER_VAL);
      break;

      case MBR_DONT_RECEIVE:
      break;
    }

    if ( MBRProcess.bBitRecState >= MBR_MAX_STATES )
    {
      MBRProcess.bBitRecState = MBR_FALLING;
    }
    if ( MBRProcess.bBitCounter >= (MBUS_MAX_PACKET_LEN * 8) )
    {
      MBRProcess.bBitRecState = MBR_DONT_RECEIVE;
      MBRProcess.bReceived    = 1;
    }
  }
}
[/codesyntax]

[lang_ru]Разберем его по порядку.[/lang_ru]

[lang_ru]В строке 188 мы проверяем, а надо ли нам воомще что-то принимать. Иногда бывают такие моменты, что лучше вообще ничего не слушать.[/lang_ru]

[lang_de]In der Zeile 188 wir schauen, ob wir überchaupt was hören mussen. Es gibt Momente, wann man lieber gar nicht hören soll. [/lang_de]

[lang_ru]Если же мы решили, что нам все таки стоит послушать, что в мире творится, то далее смотрим, в каком месте находится наша система приема сообщений — в каком состоянии приема.[/lang_ru]

[lang_de]Falls wir doch was hören wollen, was in der Welt passiert, dann prüfen wir, in welhem Zustand befindet sich unsere Empangssystem.  [/lang_de]

[lang_ru]Всего их 4:[/lang_ru]

[lang_de]Es gibt insgesamt 4 Zustände: [/lang_de]

[lang_ru]case MBR_WAITING: — Тут мы находимся, когда мы только только начали прием, или же мы уже приняли очередной бит, и ждем, когда же нам пошлют следующий, этакое междубитие. От этого пункта мы переходим к следующему без задержек.[/lang_ru]

[lang_de]case MBR_WAITING: — Hier sind wir, wenn wir erst angefangen mit dem Empfang, oder schon haben ein oder anderen Bit empfangen und warten auf den nächsten Bit. Ohne Warten gehen wir zu nächsten Zustand[/lang_de]

[lang_ru]case MBR_FALLING: — И так — пин упал в 0. Самое время засечь то самое время, сколько наш пин пробудет в этом состоянии 0.[/lang_ru]

[lang_de]case MBR_FALLING: — Also, Pin ist in 0 gestzt. Es ist gerade die Zeitpunkt zu merken, wie lange den Pin in 0 Zustand bleibt.[/lang_de]

[lang_ru]Выставляем параметры таймера, обнуляем его счетчик и устанавливаем способ следуюго входа в наше прерывание, уже по восходящему фронту.[/lang_ru]

[lang_de]Dafür starten wir Teimer, und setzen wir die external Interrupts Parametern so, damit wir bei der Steigende Flange wieder hier landen können. [/lang_de]

[lang_ru]case MBR_RISING: — Тут начинается самое интересное — определение времени, которорое прошло между спадающим и восходящим фронтом по значению счетчика таймера. И в соответствии с длительностью уже выставляется текущий бит в 0 или 1. Далее мы увеличиваем счетчик принятых битов, ставим способ входа в наше прерывание опять по спадающему фронту, и ставим статус приема уже в MBR_FALLING.[/lang_ru]

[lang_de]case MBR_RISING: — Hier fängt das Interesante — die Definition der Zeit, die vergangen ist zwieschen der falende und steigende Flanken. Das kann man mit dem Timer Kounter definieren. Und bahängig von der Dauer wird das Bit entwere als 0, oder 1 erkannt. Als nächstes, inkrementieren wir den Bitzähler, setzen das external Interrupt auf fallende Flanke, und stezen den nächsten Zustand auf  MBR_FALLING. [/lang_de]

[lang_ru]И так по кругу.[/lang_ru]

[lang_de]Und so fahren wir in Kreisen. [/lang_de]

[lang_ru]Опытный читатель скажет, а как же мы определим, когда пакет закончился то? А то ведь так можно безконечно биты принимать, когда-то надо бы и определиться, что биты для этого пакета закончились и пошли уже биты следующего.[/lang_ru]

[lang_de]Die erfahrene Lesern werden fragen, wie erkennt man den, wan Paket zu Ende ist? Sonst bleiben wir in den Kreis für immer. [/lang_de]

[lang_ru]Правильно! Для этого в строке 227 стоит вызов функции SWTLoad (SWT_MBUS_PACKET_TIMER, SWT_MBUS_PACKET_TIMER_VAL);, которая устанавливает софтовый таймер на 6 милисекунд. Я тут пробовал разные значения и именно с этим получил самые хорошие результаты определения конца пакета.[/lang_ru]

[lang_de]Genau dafür haben wir in der Zeile 227 den Timer auf 6 Milisekunden  gestarted:  SWTLoad (SWT_MBUS_PACKET_TIMER, SWT_MBUS_PACKET_TIMER_VAL); Ich habe verschiedene Zeiten hier ausprobiert, dieser Wert passt am Besten dafür. [/lang_de]

[lang_ru]Значит, таймер запустили, теперь надо бы его и обработать:[/lang_ru]

[lang_de]So. Timer ist gestartet. In dem Hardware-Timer ist die Abarbeitung von dem: [/lang_de]

[lang_ru]В аппаратном таймере происходит проверка нашего софтверного таймера:[/lang_ru]

[codesyntax lang="c" lines_start="418" container="div" title="Software Timer Check" ]

 if ( SWTFlag(SWT_MBUS_PACKET_TIMER) )
 {
   SWTClear(SWT_MBUS_PACKET_TIMER);
   MBus_ReceivedPacket();
 }

[/codesyntax]

[lang_ru]И, если софтверный таймер сработал, вызывается функция MBus_ReceivedPacket ();:[/lang_ru]

[lang_de]Und wenn der Timer abgelaufen ist, wird die Funktion MBus_ReceivedPacket (); aufgerufen: [/lang_de]

[codesyntax lang="c" lines_start="255" container="div" title="MBus_ReceivedPacket();" ]

/*
 * Called on Receive timeout, sets a flag, that data received, and stops receive process
 */
void MBus_ReceivedPacket(void)
{
  MBUS_RX_TIMER_TCCR = 0;
  MBRProcess.bBitRecState = MBR_DONT_RECEIVE;
  MBRProcess.bReceived = 1;
  SWTLoad( SWT_MBUS_ANSWER_TIMER, SWT_MBUS_ANSWER_AFTER_REQUEST_TIMER_VAL );
}

[/codesyntax]

[lang_ru]в которой мы ставим наш приемник в состояние неприема — то самое 4-е состояние MBR_DONT_RECEIVE, вывешиваем флаг, что данные приняты, и запускаем уже другой таймер для задержки между приемом и отправкой ответа. Я опять же поэкспериментировал, и понял, что вот прямо сразу после того, как мы внимательно выслушали команду, лучше не болтать, а малость подождать, а то не поймут ведь.[/lang_ru]

[lang_de]In der Funktion setzen wir unser Empfänger in den gehöhrlose Zustand — 4. Zustand: MBR_DONT_RECEIVE, setzen Flag, dass die Daten empfangen sind (MBRProcess.bReceived ), starten noch ein Timer, der für die Stille sorgt. Ich habe ein bisschen experimentiert, und habe herausgefunden, dass man sofort nach dem Empfang lieber leise bleiben soll. Sonst wird man uns nicht verstehen.[/lang_de]

[lang_ru]Ну а далее все просто — в функции, которая у нас работает на каждом проходе основного цикла программы, мы проверяем этот флаг MBRProcess.bReceived на предмет наличия в нем 1, и обрабатываем данные.[/lang_ru]

[lang_de]Und weiter ist alles simple. In der Funktion, die bei dem main Zyklus aufgerufen wird, wird der Empfangs-Flag MBRProcess.bReceived überprüft, und wenn der gesetzt ist, werden die Daten abgearbeited. [/lang_de]

[lang_ru]Про то, как мы общаемся с шиной, я расскажу через часик, а то тут много текста получилось. До скорого![/lang_ru]

[lang_de]Das war es für Heute. Bis Später![/lang_de]

P.S.:

[lang_ru]Совсем забыл. Обновленные прошивки: mmp3p_v_01_01 и xilinx_v_01_01.

Вот.[/lang_ru]

[lang_de]Habe ganz fergessen: die neue Firmware:  mmp3p_v_01_01 und xilinx_v_01_01. [/lang_de]

10 комментариев to “Mazda MP3 Player — Продолжение 3|Mazda MP3 Player — Dritte Folge”

  1. olzhan Says:

    Прочитал с интересом но не хватает опыта работы с микроконтролерами. Вертится такой вопрос в голове — а намного ли проще будет устройство которое только общается по M-Bus с головным устройством и ключами управляет каким либо MP3 плэером, коих сейчас валом по 5 долларов за штуку. Т.е. не нужно будет думать за битрейт файла, работу с диском и т.д. Просто возможно такому новичку как я будет проще собрать такое устройство. X-Car Audiolink раздражает своей ценой (у нас порядка 400 долларов) и ограниченностью(тлеет надежда, что Вы разберетесь с CAN интерфейсом стандартного маздиного экранчика). Да и просто было бы приятней собрать своими руками)). СПАСИБО за проделанный труд!!!

  2. MasterAlexei Says:

    Ого, это где ж у него такая цена? У нас на E-Bay можно за 99 евро найти.

    Просто управлять готовым плеером — думаю можно, но тогда надо найти способ подключиться к этому готовому плееру. Т.е. надо сам плеер препарировать, что не всегда является возможным, так как сейчас их компонуют довольно мелко, глаза поломаешь, пока найдешь, где что и откуда растет. Ну и потом это будет уже не монолитная конструкция, а набор проводов, торчащих в разные стороны, что в машине не приемлимо. Там вибрация постоянная, и что нибудь да отвалится. А так — думаю — можно и такое сделать. Про экран мазды — есть такая задумка, я ее все еще прорабатываю. Но тут все дело в том, что надо ставить свой контроллер между дисплеем и остальным миром. А моя машина еще на гарантии, хоть и частичной, и я не знаю, как к этому отнесется ОД (официальный диллер). Но я думаю в эту сторону. Как всегда — не хватает времени свободного на все.

  3. olzhan Says:

    Цена такая на него близ города Актау, западный Казахстан. Надеюсь на Казахстан никаких обид не затаили?)) Оченно мне импонирует что земляки такие вещи творить способны. Я и сам с Алматы, токо Политех оканчивал. В качества плеера я в руках верчу ФМ модулятор китайского производства- платка 3см диаметром, питание 12В, разъемы под USB и SD, дисплейчик отображающий ID теги, три кнопки Play, Prev,Next-просто контакты. И всего 500тенге или 2 евро. Их не жалко и с десяток в экспериментах попортить. У головы есть ниша под MD проигрыватель прикрытая пластиковой пластинкой. Очень красиво получатся эту пластинку пропилить- будто у головы появились USB и SD разъемы. Вот такие фантазии. Спасибо!

  4. MasterAlexei Says:

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

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

  5. Rewerd Says:

    Хотелось бы узнать как обстоят дела с чтеним МР3 по USB, если эта возможность предусмотренна!?

    Спасибо!

  6. MasterAlexei Says:

    Смотря что имеется ввиду. Тот USB порт, что на плате — это обычный UART от меги. И на компе он как обычный USB<->Serial конвертер распознается и на данный момент только для отладочной инфы используется.

    Идея была по этому порту заливать музыку на плеер, но это будет требовать много времени, так как скорости там не шибко шустрые, по этому я начал копать в сторону возможности копирования с CF карточки на винт. Но пока все так и осталось в зачаточном состоянии, так как время — оно такое. Вроде оно и есть, и как бы его и нет. В общем — как только — так сразу.

    Если же имеется ввиду возможность чтения файлов с USB накопителей, подключаемых к плееру — такой возможности не рассматривалось, по причине не поддерживаемости мегой USB-on-the-Go, или как там его. В общем — нету в этой меге USB встроенного, а самому реализовывать его не охота, да и есть вероятность, что в мегу он не влезет просто. Ну и железо подгонять придется.

  7. Rewerd Says:

    Спасибо за скорый ответ!

    Ввиду имелся 2 вариант.

  8. Rewerd Says:

    Жаль, хотел поддержку USB-stick в Mazde3 сделать.

    Будем копать дальше!

  9. MasterAlexei Says:

    Для этого можно прикупить уже готовые девайсы типа USB-Link кажется или MP3-Link называются. На E-Bay их полно по 99 долларей.

  10. Mazda MP3 Player — Продолжение 4 | Fun Electronic Says:

    [...] Analyzer V. 3.0marshallab on Мои инструменты: Logic Analyzer V. 3.0MasterAlexei on Mazda MP3 Player — Продолжение 3 МеткиБезопасность Выпайка Инструменты Кабель [...]

Leave a Reply

You must be logged in to post a comment.