MIDI плеер на восьми Floppy. Или как электронщик с ума сходил

от автора

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

готовый девайс

Делать на Arduino как остальные? Да вы что, серьёзно? F*uck the system, как говорится! Решено было делать на Atmega8A, потому что только она и была под рукой. Провода тоже для слабаков, поэтому я отыскал HC-05 (зачем лишние сопли?).

Поехали!

Схема

Первый этап, как обычно, схема. С ней проблем нет.

схема

Она простая и без лишних наворотов.

Плата

Плата тоже делается без особого напряжения при помощи фоторезиста. Раскидал за 10 минут и изготовил за час.

Разводка платы


Пишем код

Теперь самое интересное — программирование. Писать решил на C, дабы сэкономить время. Но не успел начать, как уже грабли.

Грабли заключаются в управлении флопами. Как известно, если Direct pin = 0, а на Step давать импульсы, то флоп шагает вперёд, а если Direct pin = 1, то назад, но у флопа всего 80 шагов. Мало, что делать? Решение простое. Флоп умеет делать полшага, если просто менять состояние Step, а не пульсировать его. Делать это лучше так:

Step ^= (1<<pin); 

Первая проблема решена! Дальше реализация всей функции управления.

void output(int drive){                                                     // drive - номер флопа 1 - 8 	int position = drive - 1;                                            //пересчёт на позицию в массивах и байтах 0-7 			if(currentPosition[position] >= max)direct |= 1 << position; // direct - переменная char (8 бит). Ставим нужный бит, если в крае 			if(currentPosition[position] <= 0)direct &= ~(1<<position);     //обнуляем его, если мы в нуле 					if(direct & (1<<position)){                                      //проверка состояния 						back(drive);                     //шагаем назад 						currentPosition[position]--; //уменьшаем позицию текущего флоппи 					}else{ 			 		forward(drive);                        //шагаем вперёд 					currentPosition[position]++;   //увеличиваем её 				} } 

Сделали! Теперь таймеры. Таймер ставим в CTC mode с делением на 8 и разрешаем прерывание по Output Compare (далее OC). В OCR кладём 40. Примерно раз в 40 мкс наступает событие OC. Обработчик прерываний довольно ёмкий.

Для любознательных

void Action(){  		if(fr1 != 0){ 		currentTick[0]++;                     //считаем тики таймера 			if(currentTick[0] >= fr1){ //fr* - периоды каналов в мкс 			output(1); 			currentTick[0]=0;            //добежали - обнуляем 			} 		}; 		if(fr2 != 0){ 		currentTick[1]++; 			if(currentTick[1] >= fr2){ 			currentTick[1]=0;	 			output(2); 			} 		}; 		if(fr3 != 0){ 		currentTick[2]++; 			if(currentTick[2] >= fr3){ 				output(3); 				currentTick[2]=0; 			} 		}; 		if(fr4 != 0){ 		currentTick[3]++; 			if(currentTick[3] >= fr4){ 				currentTick[3]=0; 				output(4); 			} 		}; 		if(fr5 != 0){ 		currentTick[4]++; 			if(currentTick[4] >= fr5){ 			currentTick[4]=0; 				output(5); 			} 		}; 		if(fr6 != 0){ 		currentTick[5]++; 			if(currentTick[5] >= fr6){ 			currentTick[5]=0; 			output(6); 			} 		}; 		if(fr7 != 0){ 		currentTick[6]++; 			if(currentTick[6] >= fr7){ 				currentTick[6]=0; 				output(7); 			} 		}; 		if(fr8 != 0){ 		currentTick[7]++; 			if(currentTick[7] >= fr8){ 				currentTick[7]=0; 				output(8); 			} 		}; } ISR(TIMER2_COMP_vect){ Action(); } 

Теперь связь с компом. Здесь поступим так. Передаётся строка с макросом в заголовке (C/F) ->тело (число)->окончание пакета (‘;’). Во-первых, обработка через машину состояний:

void parse(){ char data = UDR; 	switch(data){ 		case 'C': tmp_int = 0; SM= data; break;   // С - Это макрос канала 		case 'F': tmp_int = 0; SM= data; break;   // F - частоты 		case '0': 		case '1': 		case '2': 		case '3': 		case '4': 		case '5': 		case '6': 		case '7': 		case '8': 		case '9': tmp_int = tmp_int * 10 + (data -'0'); break; 		case ';': switch(SM){ 						case 'C': channel=tmp_int; break; 						case 'F': freq = tmp_int; break; 					}; play(freq, channel); break;  //в play пересчитывается период с учётом тактовой частоты и записывается в fr* 					case 'R' : resetAll(); break; 		default: break; 	} } 

Во-вторых, приём только в состоянии Idle:

while ( UCSRA & (1<<RXC))parse(); 

— Ну, всё уже?
— Нет! А чем управлять?

Программу управления писать с нуля было влом, поэтому я добавил функционал в свою программу управления катушкой Теслы (HETC control terminal). Наркомания? Конечно. С её интерфейсом можно разобраться самому, писать много не буду. Единственное, что надо в начале выбрать Floppy и COM-порт устройства, далее Connect.

Да, можно и без блюпупа, это просто моя заморочка.

Выбираем миди-файл иии…

Исходники

Исходники + прошивка.

ссылка на оригинал статьи http://habrahabr.ru/post/253189/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *