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

Обсуждаем цифровые устройства...
oleg88
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Сб окт 24, 2015 20:37:56
Откуда: nr. Moscow

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

Сообщение oleg88 »

[uquote="da-nie",url="/forum/viewtopic.php?p=3246529#p3246529"]Горячая замена карты не поддерживается.[/uquote]Да я так и подумал. В этом случае проверку на наличие 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 файла
 }
 
 //запускаем основное меню
...
Реклама
Аватара пользователя
da-nie
Говорящий с текстолитом
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.
Контактная информация:

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

Сообщение da-nie »

В этом случае проверку на наличие TAP файлов было бы логично сделать, перед тем как отображать основное меню.
Для этого придётся сперва обегать все каталоги. А файлов (каталог тоже ведь файл) может быть десятки тысяч. Вам не понравится ждать реакции в этом случае. :)
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Реклама
san010101
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 02, 2015 10:37:31

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

Сообщение san010101 »

Отладил загрузку tap
На данном этапе это нормально.
Все таки хочу запись реализовать, подскажите как это делается.
Аватара пользователя
da-nie
Говорящий с текстолитом
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.
Контактная информация:

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

Сообщение da-nie »

Логично, что это делается в обратном порядке по отношению к выдаче. :) Считаете такты между перепадами уровней входного сигнала и сравниваете с некоторым окном допуска для пилот-тона, синхросигнала, единицы и нуля. Сперва ждёте длительный пилот-тон. Потом синхросигнал, если пилот-тон был достаточной длины. А потом переходите к приёму данных и до окончания сигнала (пауза превысила допуск). То, что набрали - сохраняете в файл. Всё.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Реклама
Эиком - электронные компоненты и радиодетали
san010101
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 02, 2015 10:37:31

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

Сообщение san010101 »

По реализации, использовать АЦП для входа сигнала?
Каким образом вести подсчет. Надеюсь не много запросил :)
Реклама
Аватара пользователя
da-nie
Говорящий с текстолитом
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.
Контактная информация:

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

Сообщение da-nie »

Там даже ЦАП не нужен, если брать сигнал со спектрума - достаточно цифрового порта с возможностью входа в 5 В (ну или делитель, или диоды чтобы понизить до 3 В).
А считать просто - заводите таймер и смотрите, сколько отсчётов между перепадами сигнала. Сравниваете с таблицей для сигналов и делаете вывод о том, какой сигнал принимаете сейчас. Таблицу же строите исходя из длительности сигналов в тактах Z80. Частота же спектрума 3.5 МГц.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Реклама
san010101
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 02, 2015 10:37:31

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

Сообщение san010101 »

Код: Выделить всё

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, все в эмуляции :))) ))
Аватара пользователя
da-nie
Говорящий с текстолитом
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.
Контактная информация:

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

Сообщение da-nie »

Протестировал получается 1614..1610 когда как. Я так понимаю это 3223/2 в точности должно быть 1646
Тот таймер, что используется для выдачи подходит и для считывания. И длительности сигналов такие же, разумеется. Просто добавьте к ним допуск.
Как выявить синхросигналы?
Точно так же, как и остальные. :) У синхросигнала вполне определённая длительность и он ожидается всегда после пилот-тона.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
san010101
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 02, 2015 10:37:31

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

Сообщение san010101 »

Код: Выделить всё

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гц и легко могу пропустить синхронизацию посчитав её за пилот. Ведь как только у меня нет ни чего на входе то прерывание завершается.
san010101
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 02, 2015 10:37:31

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

Сообщение san010101 »

Код: Выделить всё

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 */
}
Сделал, работает.
san010101
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 02, 2015 10:37:31

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

Сообщение san010101 »

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

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

Сообщение san010101 »

Код: Выделить всё

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Гц держит, определяет. С этим все понятно.
Теперь нужно синхроимпульсы отработать.
Первый по высокому фронту, а второй по низкому.
Пока не получилось, может, что пропустил ?
Аватара пользователя
da-nie
Говорящий с текстолитом
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.
Контактная информация:

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

Сообщение da-nie »

Пока не получилось, может, что пропустил ?
Этого не знаю. :) Я ведь вам показал, где взять программу-декодер. В ней всё есть. :)
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
oleg88
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Сб окт 24, 2015 20:37:56
Откуда: nr. Moscow

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

Сообщение oleg88 »

[uquote="da-nie",url="/forum/viewtopic.php?p=3161603#p3161603"]Обновление версии ПО.
Теперь поддерживаются SDHC-карты.[/uquote]Все забываю сказать :) Практически сразу как вышла эта версия прошивки, я ее попробовал и столкнулся с глюком, который легко воспроизводится. На карте создаем папку, в которую кладем файл. Вставляем карту в магнитофон, заходим в папку, выбираем файл и его загружаем. Выходим в корень папки и видим на экране абракадабру. Нажимая кнопки вниз/вверх видим еще десятка два какой-то абракадабры опознанных как папка, т.е. появляется десятка два каких-то папок.
Аватара пользователя
da-nie
Говорящий с текстолитом
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.
Контактная информация:

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

Сообщение da-nie »

А если карту на ошибки проверить, глюк тоже воспроизводится? У меня подобное было, когда карта не отмонтировалась после записи.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
oleg88
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Сб окт 24, 2015 20:37:56
Откуда: nr. Moscow

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

Сообщение oleg88 »

да
Аватара пользователя
da-nie
Говорящий с текстолитом
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.
Контактная информация:

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

Сообщение da-nie »

Жаль. Значит, придётся разбираться. :( Но вроде бы я там ничего такого не менял, кроме способа адресации...
И ещё вопросы:
1) А старые версии (без SDHC) таким не страдали?
2) Какой объём карты?
3) На картах меньшего объёма глюк тоже есть?
4) Может быть, карте не хватает питания и она просто "теряется" со временем?
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
oleg88
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Сб окт 24, 2015 20:37:56
Откуда: nr. Moscow

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

Сообщение oleg88 »

[uquote="da-nie",url="/forum/viewtopic.php?p=3378739#p3378739"]А старые версии (без SDHC) таким не страдали?[/uquote]Использую версию 2.00 и такого не замечал (правда, пользуюсь не активно, ибо в основном использую эмулятор дисковода). Во всех последующих версиях что-то да глючило. В том числе и в версии о которой был разговор начиная с сообщения Ср мар 01, 2017 08:20:11 и далее, у меня этот глюк с абракадаброй в имени одного файла так и остался. Так что я остановился на версии 2.00.
[uquote="da-nie",url="/forum/viewtopic.php?p=3378739#p3378739"]2) Какой объём карты?
3) На картах меньшего объёма глюк тоже есть?[/uquote]Карта объемом 1Гб, отформатирована стандартным образом. Карты бОльшего объема не использовал, ибо весь этот гимор с подготовкой карты считаю ненужным, т.е. овчинка выделки не стоит.
[uquote="da-nie",url="/forum/viewtopic.php?p=3378739#p3378739"]4) Может быть, карте не хватает питания и она просто "теряется" со временем?[/uquote]Плата-то используется та же самая, я только PIC переставляю с разными версиями.
Ser1961
Открыл глаза
Сообщения: 64
Зарегистрирован: Ср мар 25, 2015 05:49:33

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

Сообщение Ser1961 »

SD2Gb в новой версии всё нормально.
Аватара пользователя
da-nie
Говорящий с текстолитом
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.
Контактная информация:

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

Сообщение da-nie »

Вот я тоже такого раньше не замечал. :dont_know: Может быть, карта где-то отваливается и перестаёт правильно передавать данные?
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Ответить

Вернуться в «Цифровая техника»