Важная информация

User Tag List

Страница 13 из 17 ПерваяПервая ... 91011121314151617 ПоследняяПоследняя
Показано с 121 по 130 из 164

Тема: ROM-плеер на ардуино

  1. #121
    Veteran
    Регистрация
    22.02.2014
    Адрес
    г. Курган
    Сообщений
    1,657
    Спасибо Благодарностей отдано 
    218
    Спасибо Благодарностей получено 
    301
    Поблагодарили
    212 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от ivagor Посмотреть сообщение
    С кнопкой это ROM-DUMPER
    А чисто программный - ROM-REAPER
    Ясно.
    Значит я не внимательно читал описание, и упомянутую идею Дампера, принял за необходимость аналогичной доработки.
    Но с другой стороны, не имея большого желания записывать ROM файл через магнитофонный выход, и дальнейшую его обработку, сделал выгрузку содержимого ПЗУ сразу на SD-карту. Т.к. по любому собирался втыкать функции записи файла на SD-карту, принятого от Вектора.

    Сорькаю, ТС-у за отклонение от темы.

  2. #121
    С любовью к вам, Yandex.Direct
    Размещение рекламы на форуме способствует его дальнейшему развитию

  3. #122
    Master Аватар для Improver
    Регистрация
    06.02.2018
    Адрес
    г. Волгоград
    Сообщений
    975
    Спасибо Благодарностей отдано 
    428
    Спасибо Благодарностей получено 
    396
    Поблагодарили
    221 сообщений
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от KTSerg Посмотреть сообщение
    До такого я не допетрил, но заметил, что длительность полупериода должна быть кратной 16. Т.е. на 112, 128, 156, 172 ... таймингах нормально грузит...
    Стоп, 112 и 128 кратно 16, а 156 и 172 -- уже нет... :-\ Ближайшие к ним числа, кратные 16 -- это 160 и 176.

    Кстати, задержка между байтами одного размера на любых скоростях выше 256 мкс вполне логически объяснима, т.к. она скорее всего вызвана недостаточным быстродействием Вектора на обработку байта, которое остаётся постоянным при любой скорости.

    Полагаю, можно будет выделить ещё задержки на отрисовку блоков и т.п., и, допустим, при передаче данных в пределах одной строки можно будет ещё немного сократить эти интервалы, но смысла в этом не вижу. Почему? А потому, что, даже в текущем состоянии, задержка в 56 мкс на каждый байт увеличивает общее время вывода 40 кб всего на ~3 секунды по сравнению с выводом без этих задержек, просто нет смысла вылавливать эти дополнительные микросекунды.

    Цитата Сообщение от KTSerg Посмотреть сообщение
    Сорькаю, ТС-у за отклонение от темы.
    Прощу, если наконец-то выложишь тут свои скетчи для общественности. ;-)

  4. #123
    Veteran
    Регистрация
    22.02.2014
    Адрес
    г. Курган
    Сообщений
    1,657
    Спасибо Благодарностей отдано 
    218
    Спасибо Благодарностей получено 
    301
    Поблагодарили
    212 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от Improver Посмотреть сообщение
    Стоп, 112 и 128 кратно 16, а 156 и 172 -- уже нет... :-\ Ближайшие к ним числа, кратные 16 -- это 160 и 176.
    ...
    Да, мой косяк, просто я с 200 сразу прыгнул на 128 и потом на 112, и промежуточные значения проверял на скорую руку, и значения писал не по записям, а что вспомнил.
    Полагаю, можно будет выделить ещё задержки на отрисовку блоков и т.п., ... просто нет смысла вылавливать эти дополнительные микросекунды.
    Я смотрел на задержки при переносе принятого в память и отрисовку блоков, на это тратятся 4 байта (точнее часть одного) "00" перед "Е6" в начале каждой строки.
    Прощу, если наконец-то выложишь тут свои скетчи для общественности. ;-)

    Я ж говорил, это не скетч, т.к. не Ардуина. Пишу на Си в Keil. Будет более менее завершенный отладочный (с управлением по СОМ-порту с РС) проект выложу.
    Вот в функциях ЛВС и ROM-плеера уже объединил переменные и буферы, т.к. алгоритмы идентичны.
    Застрял пока на открытии файла для записи. Библиотека позволяет уже существующий файл открывать и в него писать, а новый только создаёт, но записывать в него отказывается, вываливает ошибку, буду пробовать...
    Последний раз редактировалось KTSerg; 12.03.2018 в 10:46.

  5. #124
    Guru
    Регистрация
    07.08.2008
    Адрес
    г. Уфа
    Сообщений
    7,842
    Спасибо Благодарностей отдано 
    654
    Спасибо Благодарностей получено 
    1,814
    Поблагодарили
    1,043 сообщений
    Mentioned
    22 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Насчет задержки между байтами. Ramiros реализовал эту фичу в своем ROM2WAV (2009 год). Правда не вынесена "на панель управления" возможность менять длительность задержки, но и так работает хорошо, и исходник доступен.
    Насчет достижимых скоростей. Эмулятор это не реал, но просто для информации. ROM2WAV с устраненной по методу Tim0xи избыточностью и Fd=24 кГц преобразует файлик 33.25 Кб в wav длительностью примерно полторы минуты. В VV с хакнутым мною загрузчиком такой файлик грузится.
    Последний раз редактировалось ivagor; 12.03.2018 в 12:19. Причина: исправил опечатку

  6. #125
    Veteran
    Регистрация
    22.02.2014
    Адрес
    г. Курган
    Сообщений
    1,657
    Спасибо Благодарностей отдано 
    218
    Спасибо Благодарностей получено 
    301
    Поблагодарили
    212 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от ivagor Посмотреть сообщение
    ...
    Насчет достижимых скоростей. Эмулятор это не реал, но просто для информации. ROM2WAV с устраненной по методу Tim0xи избыточностью и Fd=24 кГц преобразует файлик 33.25 Кб в wav длительностью примерно полторы минуты. В VV с хакнутым мною загрузчиком такой файлик грузится.
    33.25 Кб за ~1.5 мин., это видимо эквивалент того, что получилось 21 Кб за ~1 мин, при полупериоде 112мкс. Но я все-же подозреваю, что от загрузчика будет зависеть...

  7. #126
    Guru
    Регистрация
    07.08.2008
    Адрес
    г. Уфа
    Сообщений
    7,842
    Спасибо Благодарностей отдано 
    654
    Спасибо Благодарностей получено 
    1,814
    Поблагодарили
    1,043 сообщений
    Mentioned
    22 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Ближе к вечеру попробую покрутить и посмотреть, что еще можно выжать и с хакнутым загрузчиком и с оригинальными.

  8. #127
    Master Аватар для Improver
    Регистрация
    06.02.2018
    Адрес
    г. Волгоград
    Сообщений
    975
    Спасибо Благодарностей отдано 
    428
    Спасибо Благодарностей получено 
    396
    Поблагодарили
    221 сообщений
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от ivagor Посмотреть сообщение
    Насчет задержки между байтами. Ramiros реализовал эту фичу в своем ROM2WAV (2009 год). Правда не вынесена "на панель управления" возможность менять длительность задержки, но и так работает хорошо, и исходник доступен.
    Эх, если б об этом хоть кто-то намекнул ранее, то мне бы не пришлось изобретать велосипед... :-)
    Сейчас глянул исходники ROM2WAV, как я понял, там добавляется 1 сэмпл на частоте 22 кГц при любой скорости, это получается по 45 мкс. А максимальная скорость там -- 2 сэмпла на полупериод на той же частоте, что выходит в ~91 мкс на полуцикл (между байтами по 136 мкс)... Интересно, в таком виде тоже грузилось?

  9. #128
    Guru
    Регистрация
    07.08.2008
    Адрес
    г. Уфа
    Сообщений
    7,842
    Спасибо Благодарностей отдано 
    654
    Спасибо Благодарностей получено 
    1,814
    Поблагодарили
    1,043 сообщений
    Mentioned
    22 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от Improver Посмотреть сообщение
    А максимальная скорость там -- 2 сэмпла на полупериод на той же частоте, что выходит в ~91 мкс на полуцикл (между байтами по 136 мкс)... Интересно, в таком виде тоже грузилось?
    VV грузит, emu не грузит. Реал - не знаю.

    Если увеличить частоту дискретизации без включения ресемплирования, то можно получить и более высокую скорость (для стандартных загрузчиков без разницы, они это уже не грузят). Как раз при увеличении частоты дискретизации задержку стоит увеличивать до 2.

  10. #129
    Master Аватар для Improver
    Регистрация
    06.02.2018
    Адрес
    г. Волгоград
    Сообщений
    975
    Спасибо Благодарностей отдано 
    428
    Спасибо Благодарностей получено 
    396
    Поблагодарили
    221 сообщений
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    В прошедшие выходные получил посылку с известного китайского сайта, заказывал "Data Logger Shield" с ардуиной уно -- этот шилд как раз подходит для ROM-плеера, есть место, куда можно впаять схему выхода и разъём, плюс бонусом имеет на борту часы. Вот что сейчас имеем:

    Фотки

    Всё в сборе:
    Нажмите на изображение для увеличения. 

Название:	IMG_20180317_151835~.jpg 
Просмотров:	281 
Размер:	52.5 Кб 
ID:	64678

    И по отдельности:
    Нажмите на изображение для увеличения. 

Название:	IMG_20180317_151718~.jpg 
Просмотров:	292 
Размер:	47.3 Кб 
ID:	64679

    Бело-розовый проводок с разъёмом на фото -- это прямой выход с контакта D3, для опытов...
    [свернуть]

    На всём этом скетч третьей версии загрузился и заработал без проблем, Вектор грузит всё, как и ранее. Но выявился небольшой глючёк -- как оказалось вывод D10 ардуины также задействован платой "LCD Keypad Shield" для управления яркостью подсветки экрана, и во время обращения к СД-карте подсветка становится немного темнее. :-( Решения тут два: первое -- откусить или выпаять соответствующий штырь контакта на шилде с экраном и кнопками, и второе -- считать это фичей, показывающей таким образом то, что происходит обращение к карте памяти. Склоняюсь ко второму варианту. :-)

    И раз уж появился бонус в виде часов, решил его задействовать, вот новая версия скетча:

    ROM-player_4

    Для работы требуются библиотеки TimerOne, SdFat, а также стандартные LiquidCrystal, Wire и RTClib.
    Код:
    /*
     Вариант на "Data Logger Shield" и "LCD Keypad Shield"
     (на первом есть RTC -- используем для показа времени)
    
     Выход - D3
    
     "Data Logger Shield V1.0":
      SD-картридер подключен к выводам ардуино:
     * MOSI  - D11
     * MISO  - D12
     * CLK   - D13
     * CS    - D10
    
     "LCD Keypad Shield":
     Подключение экрана 1602А:
     * LCD RS pin     - D8
     * LCD Enable pin - D9
     * LCD D4 pin     - D4
     * LCD D5 pin     - D5
     * LCD D6 pin     - D6
     * LCD D7 pin     - D7
     * LCD R/W pin    - GND
     * LCD 5V pin     - 5V
     * Кнопки         - A0
     */
    
    // include the library code:
    #include <LiquidCrystal.h>
    #include <SdFat.h>
    #include <TimerOne.h>
    #include <Wire.h>
    #include "RTClib.h"
    
    RTC_DS1307 RTC;
    
    // initialize the library with the numbers of the interface pins
    LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
    
    SdFat sd;
    SdFile romFile;
    
    #define filenameLength    100      // максимальная длина имени файла
    char fileName[filenameLength + 1]; // имя текущего файла
    char sfileName[13];                // короткое имя текущего файла
    int currentFile = 1;               // текущая позиция в директории
    int maxFile = 0;                   // всего позиций в лиректории (файлов и поддиректорий)
    byte isDir = 0;                    // признак того, что текущая позиция -- это директория
    
    byte BLs = 0x01;    // начальный блок
    unsigned int Nbt;   // размер файла, байт
    
    volatile byte BUFF[256];       // буфер данных
    volatile unsigned int CRB = 0; // индекс чтения из буфера
    volatile byte bBit = 15;       // индекс читаемого полубита
    unsigned int CWB = 0;          // индекс записи в буфер
    unsigned int CRB_temp = 0;     // временная переменная для CRB
    
    // Заголовок
    byte SB[27] = { 
      0x4E, 0x4F, 0x44, 0x49, 0x53, 0x43, 0x30, 0x30, // NODISK00
      0x31, 0x34, 0x30, 0x32, 0x31, 0x38,             // дата: 140218
      0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // имя программы
      0x20, 0x20, 0x20, 0x00, 0x00 };
    
    char DT[15] = {
      '0', '0', ':', '0', '0', ':', '0', '0', ' ',
      '0', '0', '/', '0', '0', 0x00 };
    
    volatile int Tpp = 200; // Начальная длительность задержки сигнала в микросекундах (один полупериод)
    volatile int Tb  = 64;  // Дополнительная задержка сигнала на начало байта в микросекундах
    
    const int p = 3; // номер пина, на который будет вывод сигнала
    
    const int BT_none   = 0; // константы -- коды нажатой кнопки
    const int BT_right  = 1;
    const int BT_up     = 2;
    const int BT_down   = 3;
    const int BT_left   = 4;
    const int BT_select = 5;
    
    void setup() {
      pinMode(p, OUTPUT);  // объявляем пин как выход
      digitalWrite(p, LOW);
      pinMode(10, OUTPUT); // CS для SD-картридера
      digitalWrite(10, HIGH);
      lcd.begin(16, 2);    // объявляем размер экрана 16 символов и 2 строки
    
      Timer1.initialize(Tpp);               // инициализировать timer1, и установить период Tpp мкс.
      Timer1.attachInterrupt(SendHalfBit);  // прикрепить SendHalfBit(), как обработчик прерывания по переполнению таймера
      Timer1.stop();
    
      Wire.begin();
      RTC.begin();
      if (! RTC.isrunning()) {
        printtext("RTC is NOT run!",0);
        // following line sets the RTC to the date & time this sketch was compiled
        RTC.adjust(DateTime(__DATE__, __TIME__));
        delay(1000);       // ждем 1 с
      }
      //RTC.adjust(DateTime(__DATE__, __TIME__));
    
      while (!sd.begin(10,SPI_FULL_SPEED)){ // SD-карта готова?
        printtext("SD-card failed!",0);
        tone(p, 200, 100); // нет -- включаем на 200 Гц на 100 мс
        delay(3000);       // ждем 3 с
      }
      printtext("SD-card is OK.",0);
    
      sd.chdir();            // устанавливаем корневую директорию SD
      getMaxFile();          // получаем количество файлов в директории
      seekFile();            // переходим к первому файлу в директории
    }
    
    void loop() {
      DateTime now = RTC.now();
      DT[0] = now.hour()/10 + '0';              // перевод из целого в символ
      DT[1] = now.hour()%10 + '0';              // часы
      DT[3] = now.minute()/10 + '0';            // минуты
      DT[4] = now.minute()%10 + '0';            // минуты
      DT[6] = now.second()/10 + '0';            // секунды
      DT[7] = now.second()%10 + '0';            // секунды
      DT[9] = now.day()/10 + '0';               // день
      DT[10] = now.day()%10 + '0';              // день
      DT[12] = now.month()/10 + '0';            // месяц
      DT[13] = now.month()%10 + '0';            // месяц
      printtext(DT,1);                          // выводим время и дату
    
      int button = getPressedButton(); // какая кнопка нажата?
      while(getPressedButton()!=BT_none) { // Ждём, пока не будет отпущена кнопка
        delay(50); 
      }
      switch (button)
      {
      case BT_right: // вход в директорию, или запуск файла на воспроизведение
        if(isDir==1) { //Если это директория, то переход в неё
          sd.chdir(fileName, true);
          getMaxFile();
          currentFile=1;
        } 
        else {         // если не директория -- пробуем воспроизвести файл
          if(romFile.cwd()->exists(sfileName)) {
            printtext("Not ROM-file",1);
            if (Nbt != 0xFFFF) { // проверяем размер файла
              for (int i=0;12;i++){ // цикл по имени файла
                if (sfileName[i]=='.'){                 // ищем точку в имени файла
                  if ((sfileName[i+1]|0x20)=='r') {     // проверяем следующий символ (расширения) == 'r'|'R'
                    if (((sfileName[i+2]|0x20)=='o')|((sfileName[i+2]|0x20)=='0')) {   // == 'o'|'O'|'0'
                      if ((sfileName[i+2]|0x20)!='0') { // проверка на вывод нулевого блока по расширению файла
                        BLs = 0x01; // с первого блока
                      }
                      else { 
                        BLs = 0x00; // с нулевого блока
                      }
                      if ((sfileName[i+3]|0x20)=='m') { // == 'm'|'M'
                        printtext("Playing...",1);
                        int RCrom = PlayROM(sfileName, i);// Передаём короткое имя файла и позицию точки в качестве параметров
                        switch (RCrom)                    // Проверяем код возврата
                        {
                        case 0:
                          printtext("Done.",1);           // Всё закончилось успешно.
                          break;
                        case 1:
                          printtext("Stopped",1);         // Сообщение об остановке
                          while(getPressedButton()!=BT_none) { // Ждём, пока не будет отпущена кнопка
                            delay(50); 
                          }
                          break;
                        default:  
                          printtext("ERROR!",1);          // Сообщение об ошибке
                        }
                        digitalWrite(p, LOW);
                      }
                    }
                  }
                  break;
                }
              }
            }
            else {
              printtext("File is too big",1);
            }
          } 
          else {
            printtext("No File Selected",1);
          }
          delay(1000);           // ждем 1 с
        }
        break;
      case BT_left: // возврат в корневую директорию, ремарка ниже:
        //SDFat has no easy way to move up a directory, so returning to root is the easiest way. 
        //each directory (except the root) must have a file called ROOT (no extension)
        sd.chdir(true);
        getMaxFile();
        currentFile=1;
        break;
      case BT_up: // вверх по файлам в директории
        currentFile--;
        if(currentFile<1) {
          getMaxFile();
          currentFile = maxFile;
        }
        break;
      case BT_down: // вниз по файлам в директории
        currentFile++;
        if(currentFile>maxFile) { 
          currentFile=1; 
        }
        break;
      case BT_select: // выход в настройки...
        printtext("Setup",0);
        printtext("Period(mks):",1);
        do {
          delay(300);
          button = getPressedButton(); // какая кнопка нажата?
          switch (button)
          {
          case BT_up:   
            if (Tpp<400) Tpp += 8;
            break;
          case BT_down:   
            if (Tpp>160) Tpp = Tpp - 8;
            break;
          }
          if (Tpp <= 264) { // Выставляем значение задержки на начало байта Tb
            Tb = 16;                        // для полупериода от 248 до 264
            if (Tpp <= 240) Tb = 264 - Tpp; // для полупериода меньше или равном 240 
          }
          else Tb = 0;                      // для полупериода больше 264
          lcd.setCursor(12,1);
          lcd.print(Tpp);
        } 
        while(button!=BT_select); // Цикл пока не будет снова нажата кнопка select
        while(getPressedButton()!=BT_none) { // Ждём, пока не будет отпущена кнопка
          delay(50); 
        }
        break;
      case BT_none: // ничего не нажато
        delay(100); 
        break;
      }
      if (button != BT_none) seekFile();  
    }
    
    //=================================================================
    int getPressedButton()  // функция проверки нажатой кнопки
    {
      int buttonValue = analogRead(0);
      if (buttonValue < 80) return BT_right;
      else if (buttonValue < 200) return BT_up;
      else if (buttonValue < 380) return BT_down;
      else if (buttonValue < 600) return BT_left;
      else if (buttonValue < 800) return BT_select;
      return BT_none;
    }
    
    void printtext(char* text, int l) {  // Вывод текста на экран в строке l с очисткой строки
      lcd.setCursor(0,l);
      lcd.print(text);
      lcd.print("                ");
    }
    
    void getMaxFile() { // считаем файлы в текущей директории и сохраняем в maxFile
      romFile.cwd()->rewind();
      maxFile=0;
      while(romFile.openNext(romFile.cwd(),O_READ)) {
        romFile.close();
        maxFile++;
      }
    }
    
    void seekFile() { // переход на позицию в директории, сохранение имени файла и показ его на экране
      romFile.cwd()->rewind();
      for(int i=1;i<currentFile;i++) { // читаем первые файлы до currentFile
        romFile.openNext(romFile.cwd(),O_READ);
        romFile.close();
      }
      romFile.openNext(romFile.cwd(),O_READ); // читаем данные текущего файла
      romFile.getName(fileName,filenameLength);
      romFile.getSFN(sfileName);
      isDir = romFile.isDir();
      if (romFile.fileSize()<=49152) { // проверка размера файла
        Nbt = romFile.fileSize();      // размер файла ОК
      }
      else {
        Nbt = 0xFFFF;                  // слишком большой для загрузки
      }
      romFile.close();
      printtext(sfileName,0);       // вывод имени текущего файла
      if (isDir==1) lcd.print('>'); // если это директория, добавляем в конце символ '>'
    }
    
    int PlayROM(char FName[], int pnt) // функция вывода файла
    {
      delay(1000);           // ждем 1 с
    
      if (romFile.open(FName,O_READ)) { // открываем файл. Открылся?
        byte BLe = Nbt/256; // всего блоков
        byte BLt;           // осталось блоков
        byte Nst;           // номер строки
        byte St;            // выводимый байт
    
        byte CSz = 0x00;    // контрольная сумма заголовка
        byte CSs = 0x00;    // контрольная сумма строки
        byte i;
        byte j;
    
        if (Nbt%256 != 0) BLe++; // корректировка количества блоков, если размер файла не кратен 256
    
        for (i=0; i<=7; i++){                // заносим в SB имя файла
          if (i < pnt) {                     // имя ещё не закончилось?
            if ((FName[i]>=0x61) && (FName[i]<=0x7A)) {
              SB[i+14] = FName[i] - 0x20;    // на заглавные буквы
            }
            else if (FName[i]!=0x7E) {       // не тильда
              SB[i+14] = FName[i];
            }
            else {
              SB[i+14] = '_';                // меняем тильду на подчёркивание, иначе это будет русская "Ч"
            }
          }
          else SB[i+14] = 0x20;              // пробелы
        }
        for (i=1; i<=3; i++){              // заносим в SB расширение файла
          if ((FName[pnt+i]>=0x61) && (FName[pnt+i]<=0x7A)) {
            SB[i+21] = FName[pnt+i] - 0x20;  // на заглавные буквы
          }
          else {
            SB[i+21] = FName[pnt+i];
          }
        }
    
        dir_t d;
        romFile.dirEntry(&d);                    // Считываем дату файла
        uint16_t AAA = FAT_DAY(d.lastWriteDate); // Сохраняем дату файла в заголовке -- день
        SB[8] = (AAA%100)/10 + '0';              // перевод из целого в символ
        SB[9] = AAA%10 + '0';
        AAA = FAT_MONTH(d.lastWriteDate);        // месяц
        SB[10] = (AAA%100)/10 + '0';
        SB[11] = AAA%10 + '0';
        AAA = FAT_YEAR(d.lastWriteDate);         // последние две цифры года
        SB[12] = (AAA%100)/10 + '0';
        SB[13] = AAA%10 + '0';
    
        // Начинаем наполнять буфер
        for (i=0; i<=3; i++){           // преамбула (4*(00H*25+55H*25))
          for (j=0; j<=24; j++){
            BUFF[lowByte(CWB)] = 0x00;
            CWB++;
          }
          for (j=0; j<=24; j++){
            BUFF[lowByte(CWB)] = 0x55;
            CWB++;
          }
        }  
    
        Timer1.setPeriod(Tpp); // Выставляем период таймера
        Timer1.start();           // Запускаем таймер............
    
        for (BLt=BLe; BLt>=1; BLt--){   // Вывод блоков данных в цикле
          CSz = BLs;
          CSz += BLe;
          CSz += BLt;
    
          for (j=0; j<=15; j++) ToBUFF(0x00);// 00h*16
          for (j=0; j<=3; j++)  ToBUFF(0x55);// 55h*4
          ToBUFF(0xE6);                      // E6h*1
          for (j=0; j<=3; j++)  ToBUFF(0x00);// 00h*4
    
          for (j=0; j<=26; j++){             // заголовок блока
            CSz += SB[j];
            ToBUFF(SB[j]);
          }
          ToBUFF(BLs);                       // начальный блок
          ToBUFF(BLe);                       // конечный блок
          ToBUFF(BLt);                       // осталось блоков
    
          lcd.setCursor(12, 1);              // выводим на экран кол-во оставшихся блоков
          lcd.print(BLt);
          lcd.print(' ');
    
          ToBUFF(CSz);                       // контр.сумма заголовка
    
          for (Nst=0x80; Nst<=0x87; Nst++){   // вывод строк (8 шт.)
            for (j=0; j<=3; j++) ToBUFF(0x00);// 00h*4
            ToBUFF(0xE6);                     // E6h*1
            CSs = Nst;
            ToBUFF(Nst);                      // номер строки
            CSs += CSz;
            ToBUFF(CSz);                      // контр.сумма заголовка
    
            // начинаем вывод строки данных
            for (j=0; j<=31; j++){      // цикл на 32 байта
              if (Nbt > 0){             // ещё есть данные?
                St = romFile.read();    // читаем очередной байт из файла
                Nbt--;
              }
              else {                    // нет -- дополняем нулями
                St = 0x00;
              }
              ToBUFF(St);               // передаём считанный байт
              CSs += St;
              if (getPressedButton()!=BT_none) { // кнопка нажата?
                Timer1.stop();          // Останавливаем таймер
                CRB = 0;                // Сбрасываем индексы.
                CWB = 0;
                bBit = 15;
                romFile.close();        // закрываем файл
                return 1;               // выход из ПП с ошибкой 1.
              }
              if (CRB_temp > CWB) {     // проверка -- не обогнало ли чтение запись?
                Timer1.stop();          // Останавливаем таймер
                CRB = 0;                // Сбрасываем индексы.
                CWB = 0;
                bBit = 15;
                romFile.close();        // закрываем файл
                return 2;               // выход из ПП с ошибкой 2.
              }
            }
            ToBUFF(CSs);                // контр.сумма строки
          }  
        }
        romFile.close(); // закрываем файл
    
        for (j=0; j<=31; j++) ToBUFF(0x00);// 00h*32 -- завершение вывода программы (?)
      }
      else tone(p, 200, 300); // нет файла -- включаем на 200 Гц на 300 мс
    
      do{                     // Ждём опустошения буфера
        delay(Tpp/64);        // задержка на вывод 1 байта (~Tpp*16/1000)
        noInterrupts();       // запрет прерываний
        CRB_temp = CRB;       // сохраняем CRB во временную переменную
        interrupts();         // разрешение прерываний
      }
      while (CRB_temp < CWB);
    
      Timer1.stop();  // Останавливаем таймер............
      CRB = 0;        // Сбрасываем индексы.
      CWB = 0;
      bBit = 15;
      return 0;       // выход из ПП с кодом 0.
    }
    
    void ToBUFF(byte SBb){     // Подпрограмма записи байта в буфер
      noInterrupts();               // запрет прерываний
      CRB_temp = CRB;               // сохраняем CRB во временную переменную
      interrupts();                 // разрешение прерываний
      if (CWB > (CRB_temp + 255)) { // Если позиция записи больше, чем позиция чтения + размер буфера - 1
        delay(Tpp);                 // Задержка (Tpp*1000 мкс = Tpp мс = 125 байт)
      }
      BUFF[lowByte(CWB)] = SBb;
      CWB++;
    }
    
    void SendHalfBit() {  // Подпрограмма вывода полубита по циклу таймера
      byte Pd=PORTD;
      if (bBit & 1){      // проверка индекса полубитов на чётность
        if (( (Pd >> p)^( BUFF[lowByte(CRB)] >> (bBit >> 1) ))&1){ // Если состояние порта и выводимый бит разные
          Pd ^= (1 << p); // инвертируем бит в позиции p
        }
      }
      else{               // чётный -- просто инвертируем порт
        Pd ^= (1 << p);   // инвертируем бит в позиции p(=3)
      }
      PORTD = Pd;         // вывод в порт p
      if (bBit > 0) {     // правим счётчики полубитов и байтов
        bBit--;
        if (bBit == 14) Timer1.setPeriod(Tpp); // Выставляем период таймера (биты)
      }
      else{
        bBit = 15;
        CRB++;
        if (CRB > 200) Timer1.setPeriod(Tpp+Tb); // Выставляем увеличенный период таймера (начало байта)
      }
    }
    [свернуть]

    Изменения по отношению к предыдущей версии минимальны: добавлены часы вместо отсчёта секунд от включения и немного оптимизированы некоторые алгоритмы (не главные).
    Исходники с библиотеками в одном архиве: ROM-player_4.7z

    Теперь, имея "генератор сигнала Вектора", можно двигаться дальше -- на второй ардуинке делать запись и сохранение данных... :-)

  11. #130
    Veteran
    Регистрация
    22.02.2014
    Адрес
    г. Курган
    Сообщений
    1,657
    Спасибо Благодарностей отдано 
    218
    Спасибо Благодарностей получено 
    301
    Поблагодарили
    212 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

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

Страница 13 из 17 ПерваяПервая ... 91011121314151617 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Портативный AY плеер.
    от Руслан в разделе Звук
    Ответов: 1
    Последнее: 16.04.2014, 08:46
  2. Service rom + 128 basic rom
    от VELESOFT в разделе Оси
    Ответов: 1
    Последнее: 24.03.2013, 04:48
  3. Плеер для pt 3
    от Руслан в разделе Музыка
    Ответов: 25
    Последнее: 14.08.2012, 19:25
  4. Advanced ROM Manager (ROM Switvcher + Prof. ROM)
    от Alex_NEMO в разделе Память
    Ответов: 4
    Последнее: 04.10.2010, 11:43
  5. AY плеер
    от newart в разделе Звук
    Ответов: 19
    Последнее: 20.07.2006, 00:03

Метки этой темы

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •