Обсуждаем цифровые устройства...
Ответить

Re: Эмулятор магнитофона для ZX-Spectrum

Сб дек 02, 2017 10:44:04

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

Код:
//----------
//глобальные переменные
//----------
const char Text_Main_Init[] PROGMEM = " Initialization \0";
const char Text_Main_Wait[] PROGMEM = " Please wait... \0";
...

//----------
//основная функция программы
//----------
int main(void)
{
 InitAVR();
 DRAM_Init();
 WH1602_Init();
 WH1602_SetTextProgmemUpLine(Text_Main_Init);
 WH1602_SetTextProgmemDownLine(Text_Main_Wait);
 SD_Init();
 FAT_Init();

 // Проверить на наличие TAP файлов
 if (FAT_BeginFileSearch()==false)
 {
  WH1602_SetTextProgmemUpLine(Text_Tape_Menu_No_Image);
  WH1602_SetTextDownLine("");
  _delay_ms(2000);
  while(1);//нет ни одного TAP файла
 }
 
 //запускаем основное меню
...

Re: Эмулятор магнитофона для ZX-Spectrum

Сб дек 02, 2017 13:27:23

В этом случае проверку на наличие TAP файлов было бы логично сделать, перед тем как отображать основное меню.


Для этого придётся сперва обегать все каталоги. А файлов (каталог тоже ведь файл) может быть десятки тысяч. Вам не понравится ждать реакции в этом случае. :)

Re: Эмулятор магнитофона для ZX-Spectrum

Чт дек 07, 2017 09:39:27

Отладил загрузку tap
На данном этапе это нормально.
Все таки хочу запись реализовать, подскажите как это делается.

Re: Эмулятор магнитофона для ZX-Spectrum

Чт дек 07, 2017 11:07:49

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

Re: Эмулятор магнитофона для ZX-Spectrum

Чт дек 07, 2017 16:13:46

По реализации, использовать АЦП для входа сигнала?
Каким образом вести подсчет. Надеюсь не много запросил :)

Re: Эмулятор магнитофона для ZX-Spectrum

Пт дек 08, 2017 15:03:05

Там даже ЦАП не нужен, если брать сигнал со спектрума - достаточно цифрового порта с возможностью входа в 5 В (ну или делитель, или диоды чтобы понизить до 3 В).
А считать просто - заводите таймер и смотрите, сколько отсчётов между перепадами сигнала. Сравниваете с таблицей для сигналов и делаете вывод о том, какой сигнал принимаете сейчас. Таблицу же строите исходя из длительности сигналов в тактах Z80. Частота же спектрума 3.5 МГц.

Re: Эмулятор магнитофона для ZX-Spectrum

Сб дек 09, 2017 10:55:18

Код:
void TIM6_DAC_IRQHandler(void)
{
  /* USER CODE BEGIN TIM6_DAC_IRQn 0 */

  /* USER CODE END TIM6_DAC_IRQn 0 */
  HAL_TIM_IRQHandler(&htim6);
  /* USER CODE BEGIN TIM6_DAC_IRQn 1 */
static uint16_t      tim6_countersec=3293;   //счетчик секунд   
static uint32_t      tim6_counterbit=0;         //счетчик загрузки bit
/********************определяем пилот-тон***********************************************************/   
 if (TapeInMode>=TAPE_IN_STOP){
   //tim6_counterbit=0;       //счетчик загрузки bit
  return;}
   
 if (TapeInMode==TAPE_IN_LEAD){
  TIM6->ARR = 2168*2;//начальное значение таймера
  if (tim6_countersec > 0) {
      tim6_countersec--;
      if (HAL_GPIO_ReadPin(T_IN_GPIO_Port, T_IN_Pin) == GPIO_PIN_SET){
         tim6_counterbit++;
      };
   }
   
 else{   
    #if Debug_TIM
         SEGGER_RTT_printf(0,"\nTAPE_IN_LEAD END tim6_counterbit=%u\n", tim6_counterbit);                  
   #endif         
    tim6_countersec = 3223;//Время воспроизведения пилот тона 2 сек.   
   tim6_counterbit=0;       //счетчик загрузки bit
  TapeInMode=TAPE_IN_STOP;
 return;}}
      
  /* USER CODE END TIM6_DAC_IRQn 1 */
}


Добавлено after 3 minutes 53 seconds:
Попробовал сделать в обработчике прерываний для TIM6 подсчет импульсов пилот-тона.
Получается в условии 2 сек крутится проверка на установку PIN_SET в единицу и счетчик.
Протестировал получается 1614..1610 когда как. Я так понимаю это 3223/2 в точности должно быть 1646

Как выявить синхро сигналы?

P.S.
Так как пока нет обвязки для входного сигнала со звуковой карты я запустил PWM (800Гц %50) от логического анализатора.
Хочу продолжить тестирование подав сигнал от ПК через звуковую карту (ПК будет воспроизводить waw с записью выгрузки, я перекомпилировал tap --> waw, нет железа под рукой (zx-spectrum, все в эмуляции :))) ))

Re: Эмулятор магнитофона для ZX-Spectrum

Сб дек 09, 2017 14:03:28

Протестировал получается 1614..1610 когда как. Я так понимаю это 3223/2 в точности должно быть 1646


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

Как выявить синхросигналы?


Точно так же, как и остальные. :) У синхросигнала вполне определённая длительность и он ожидается всегда после пилот-тона.

Re: Эмулятор магнитофона для ZX-Spectrum

Сб дек 09, 2017 17:41:52

Код:
void EXTI15_10_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */

  /* USER CODE END EXTI15_10_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15);
   
  /* USER CODE BEGIN EXTI15_10_IRQn 1 */
/********************переменные*********************************************************************/      
static uint16_t      exti15_countersec=3293;   //счетчик секунд   
static uint32_t      exti15_counterbit=0;         //счетчик загрузки bit
   
/********************определяем пилот-тон***********************************************************/   
   if (TapeInMode==TAPE_IN_LEAD){
   TIM6->ARR = 2168*2;//начальное значение таймера   
      if (HAL_GPIO_ReadPin(T_IN_GPIO_Port, T_IN_Pin) == GPIO_PIN_SET)   exti15_counterbit++;
      if (exti15_countersec > 0) exti15_countersec--;
         else{
   #if Debug_TIM
      SEGGER_RTT_printf(0,"\nTAPE_IN_LEAD exti15_counterbit=%u\n", exti15_counterbit);                  
   #endif             
            TapeInMode   =   TAPE_IN_STOP;
            exti15_counterbit   =   0;
            exti15_countersec = 3223;//Время воспроизведения пилот тона 2 сек.
            return;}
   }
  /* USER CODE END EXTI15_10_IRQn 1 */
}


Добавлено after 49 minutes 40 seconds:
Вот пробую через прерывание по входу.
Пока тестовый сигнал 800гц подаю работает. Думаю таймер тут совсем не нужен. На входе идёт сигнал с установленной частотой. Так же нет смысла его ожидать во времени. У меня тут условия что идёт декримент числа и должно две секунды пройти. Думаю убрать это. Пусть идёт счёт пока есть на входе сигнал.
Теперь момент, я ещё не решил как синхроимпульс определю. По хорошему я считаю некую последовательность на частоте 800гц и легко могу пропустить синхронизацию посчитав её за пилот. Ведь как только у меня нет ни чего на входе то прерывание завершается.

Re: Эмулятор магнитофона для ZX-Spectrum

Вс дек 10, 2017 15:56:04

Код:
void EXTI15_10_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */

  /* USER CODE END EXTI15_10_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15);
   
  /* USER CODE BEGIN EXTI15_10_IRQn 1 */
   
if (TapeInMode==TAPE_IN_LEAD){
TIM6->ARR = 2168*2;//начальное значение таймера 807Гц
//TIM6->ARR = 2272*2;//начальное значение таймера   770Гц
//TIM6->ARR = 2187*2;//начальное значение таймера   800Гц
 if (TapeIn==true){
         TIM6->CNT = 0;
        HAL_TIM_Base_Start (&htim6);
         HAL_TIM_Base_Start_IT (&htim6);         
  TapeIn=false;}
 else{
         HAL_TIM_Base_Stop (&htim6);
         HAL_TIM_Base_Stop_IT (&htim6);   
         counterbit = __HAL_TIM_GET_COUNTER(&htim6);
         if ((counterbit < 4336-20)&&(counterbit > 4336+20))  TapeInMode   =   TAPE_IN_STOP;               
    #if Debug_TIM
      SEGGER_RTT_printf(0,"\n counterbit %u\n", counterbit);                  
   #endif                
      EXTI->PR|=0x0F; //Очищаем флаг
  TapeIn=true;}   
   }
   /* USER CODE END EXTI15_10_IRQn 1 */
}


Сделал, работает.

Re: Эмулятор магнитофона для ZX-Spectrum

Пн дек 11, 2017 03:50:42

Заметил такие детали. Регистр ARR установлен 2168*2 как по даташиту что бы 807 Гц пилот формировал.
В сообщении:
#if Debug_TIM
SEGGER_RTT_printf(0,"\n counterbit %u\n", counterbit);
#endif
Получается все правильно 4336
Если на вход будет подана частота пилота 800 то мы получил 74
Если 810 то 4303
Вопрос, какое лучше число использовать в регистре.

Re: Эмулятор магнитофона для ZX-Spectrum

Вт дек 12, 2017 09:07:40

Код:
void EXTI15_10_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */

  /* USER CODE END EXTI15_10_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15);
   
  /* USER CODE BEGIN EXTI15_10_IRQn 1 */
/*********************блок переменных************************************************************/   
static const uint8_t         delta    = 50;            //дельта для диапозона пилот тона
static const uint16_t    pilot_ARR = 2168*2;      //значение таймера для пилот-тона 807Гц
static const uint16_t     syn1_ARR = 667;         //значение таймера synchro1       5247Гц
static const uint16_t     syn2_ARR = 735;         //значение таймера synchro2       4761Гц
/***********************************************************************************************/
   
/********************чтение пилот-тона**********************************************************/     
if (TapeInMode==TAPE_IN_LEAD){   
TIM6->ARR = pilot_ARR;
   
if (TapeIn==true){
         TIM6->CNT = 0;                                                      //начальное значение для отсчета
        HAL_TIM_Base_Start (&htim6);
         HAL_TIM_Base_Start_IT (&htim6);                              //включить таймер
         TapeIn=false;                                                         //переключатель на выкл. таймера
         EXTI->PR |= (0x15);                                             //Очищаем флаг и останавливаем прерывание
         return;
}
else{
         HAL_TIM_Base_Stop (&htim6);
         HAL_TIM_Base_Stop_IT (&htim6);                              //выключить таймер
         counterbit = __HAL_TIM_GET_COUNTER(&htim6);            //взять значение отсчета таймера
   
            /*проверка на ввод пилот тона, если нет сигнала то стоп прием и переход к ледующему шагу*/   
         if ((counterbit > pilot_ARR-delta) && (counterbit < pilot_ARR+delta) ) {
            #if Debug_TIM                           
               SEGGER_RTT_printf(0,"\n counterbit %u\n", counterbit);                 
            #endif               
            TapeInMode   =   TAPE_IN_LEAD;                                 //продолжим прием пилот-тона
         }
         else
         {
            #if Debug_TIM
               SEGGER_RTT_printf(0,"\n Exit %u\n", counterbit);           
            #endif               
            TapeInMode   =   TAPE_IN_SYNCHRO_1;                        //прием Synchro1           
            EXTI->PR |= (0x15);                                             //Очищаем флаг и останавливаем прерывание           
            EXTI->RTSR |= 0x15;                                             //по нарастающему фронту
         }                       
      TapeIn=true;                                                            //переключатель на старт таймера
      return;
   }   
}

/********************читаем синхросигнал 1******************************************************/
if (TapeInMode==TAPE_IN_SYNCHRO_1){
       
  TIM6->ARR = syn1_ARR;//начальное значение таймера 5247Гц
   //EXTI->RTSR |= 0x15;
   
   if (TapeIn==true){           
         TIM6->CNT = 0;                                                      //начальное значение для отсчета
        HAL_TIM_Base_Start (&htim6);
         HAL_TIM_Base_Start_IT (&htim6);                              //включить таймер
         TapeIn=false;                                                         //переключатель на выкл. таймера
         //EXTI->PR |= (0x15);                                             //Очищаем флаг и останавливаем прерывание           
         return;     
   }     
   else {
     
         HAL_TIM_Base_Stop (&htim6);
         HAL_TIM_Base_Stop_IT (&htim6);                              //выключить таймер
         counterbit = __HAL_TIM_GET_COUNTER(&htim6);            //взять значение отсчета таймера
         TapeInMode   =   TAPE_IN_SYNCHRO_2;                           //стоп прием
         EXTI->PR |= (0x15);                                               //Очищаем флаг и останавливаем прерывание           
         EXTI->FTSR |= 0x15;                                                //по спадающему фронту
     
   #if Debug_TIM
      SEGGER_RTT_printf(0,"\n Exit Synchro1 %u\n", counterbit);                 
   #endif                       
   }
   TapeIn=true;                                                               //переключатель на старт таймера
  return;}

/**************************************************************************************************/

/********************читаем синхросигнал 2******************************************************/
if (TapeInMode==TAPE_IN_SYNCHRO_2){
   
  TIM6->ARR = syn2_ARR;//начальное значение таймера 4761Гц
   //EXTI->FTSR |= 0x15;
   
   if (TapeIn==true){
         TIM6->CNT = 0;                                                      //начальное значение для отсчета
        HAL_TIM_Base_Start (&htim6);
         HAL_TIM_Base_Start_IT (&htim6);                              //включить таймер
         TapeIn=false;                                                         //переключатель на выкл. таймера
         //EXTI->PR |= (0x15);                                             //Очищаем флаг и останавливаем прерывание
     
         return;     
   }     
   else {
         HAL_TIM_Base_Stop (&htim6);
         HAL_TIM_Base_Stop_IT (&htim6);                              //выключить таймер
         counterbit = __HAL_TIM_GET_COUNTER(&htim6);            //взять значение отсчета таймера
         TapeInMode   =   TAPE_IN_STOP;                                    //стоп прием
         EXTI->PR |= (0x15);                                             //Очищаем флаг и останавливаем прерывание
         EXTI->RTSR |= 0x15;                                             //по нарастающему фронту
     
   #if Debug_TIM
      SEGGER_RTT_printf(0,"\n Exit Synchro2 %u\n", counterbit);                 
   #endif                             
   }
   TapeIn=true;                                                               //переключатель на старт таймера
  return;}

/**************************************************************************************************/

В общем попробовал дальше продолжить написание обработчика.
Вход 807Гц держит, определяет. С этим все понятно.
Теперь нужно синхроимпульсы отработать.
Первый по высокому фронту, а второй по низкому.
Пока не получилось, может, что пропустил ?

Re: Эмулятор магнитофона для ZX-Spectrum

Вт дек 12, 2017 10:46:35

Пока не получилось, может, что пропустил ?


Этого не знаю. :) Я ведь вам показал, где взять программу-декодер. В ней всё есть. :)

Re: Эмулятор магнитофона для ZX-Spectrum

Чт май 17, 2018 01:09:30

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

Re: Эмулятор магнитофона для ZX-Spectrum

Чт май 17, 2018 08:45:34

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

Re: Эмулятор магнитофона для ZX-Spectrum

Чт май 17, 2018 13:01:41

да

Re: Эмулятор магнитофона для ZX-Spectrum

Чт май 17, 2018 15:29:46

Жаль. Значит, придётся разбираться. :( Но вроде бы я там ничего такого не менял, кроме способа адресации...
И ещё вопросы:
1) А старые версии (без SDHC) таким не страдали?
2) Какой объём карты?
3) На картах меньшего объёма глюк тоже есть?
4) Может быть, карте не хватает питания и она просто "теряется" со временем?

Re: Эмулятор магнитофона для ZX-Spectrum

Чт май 17, 2018 16:43:25

А старые версии (без SDHC) таким не страдали?
Использую версию 2.00 и такого не замечал (правда, пользуюсь не активно, ибо в основном использую эмулятор дисковода). Во всех последующих версиях что-то да глючило. В том числе и в версии о которой был разговор начиная с сообщения Ср мар 01, 2017 08:20:11 и далее, у меня этот глюк с абракадаброй в имени одного файла так и остался. Так что я остановился на версии 2.00.
2) Какой объём карты?
3) На картах меньшего объёма глюк тоже есть?
Карта объемом 1Гб, отформатирована стандартным образом. Карты бОльшего объема не использовал, ибо весь этот гимор с подготовкой карты считаю ненужным, т.е. овчинка выделки не стоит.
4) Может быть, карте не хватает питания и она просто "теряется" со временем?
Плата-то используется та же самая, я только PIC переставляю с разными версиями.

Re: Эмулятор магнитофона для ZX-Spectrum

Сб май 19, 2018 08:11:28

SD2Gb в новой версии всё нормально.

Re: Эмулятор магнитофона для ZX-Spectrum

Сб май 19, 2018 08:50:51

Вот я тоже такого раньше не замечал. :dont_know: Может быть, карта где-то отваливается и перестаёт правильно передавать данные?
Ответить