
Witam.
Sesja się zbliża, więc tradycyjnie zacząłem już prokrastynować


Oto moje elektroniczne "pianino" z komputerowej klawiatury PS/2.
Od strony elektronicznej układ jest bardzo prosty - mikrokontroler ATMega, kondensatory, głośnik, gniazdo PS/2, które barbarzyńsko wyciąłem wraz z kawałkiem uszkodzonej płyty głównej, gdyż nie chciało mi się go wylutowywać i klawiatura PS/2 ze złomu, którą wspaniale oznakowałem zielonym markerem i powyciągałem kilka klawiszy by układ klawiszy przypominał klawiaturę pianina.



Na zdjęciach widać moją uniwersalną płytkę, w której siedzi m.in. Mega32 i programator USB DIY - USBAsp. Głośnik pochodzi z obudowy komputerowej.
Czas wspomnieć coś o softwarze, który jest główną częścią projektu. Być może kogoś to zainteresuje.
Jak już wspomniałem, napisałem go w C i skompilowałem pod AVR-GCC. Program dzieli się na dwie części - obsługa PS/2 i właściwy program - pianino.
Warstwa fizyczna PS/2 jest bardzo prosta. W przypadku klawiatury oprócz VCC/GND wykorzystywane są jedynie linie DATA i CLK. Opis można znaleźć m. in.
[TUTAJ] . W chwili naciśnięcia/puszczenia przycisku klawiatura przesyła 11 bitów (start, data(8), parity, stop) generując przy tym zegar na linii CLK. Zegar połączyłem z wejściem INT0 mikrokontrolera i włączyłem zewnętrzne przerwanie. Dane można odebrać na dwa sposoby - w momencie wystąpienia przerwania można odebrać wszystkie 11 bitów lub odbierać po 1 bicie w każdym przerwaniu. Ja zastosowałem drugą opcję. Dlaczego? Dzięki temu nie marnuję czasu pomiędzy bitami. Jeśli odbierałbym cały bajt, musiałbym czekać na aż klawiatura prześle wszystkie 11, a że działoby się to w przerwaniu zablokowałbym inne przerwania aż do zakończenia odczytu, co mogłoby być niepożądane w przypadku korzystania innych często występujących przerwań. Minusem jest możliwość utraty synchronizacji, kiedy na linii CLK pojawi się jakiś "śmieć" (moja klawiatura ze złomu jest lekko upośledzona i czasem je wysyła

Po odebraniu 11-go bitu, bajt trafia do kolejki klawiatury - struktury zawierającej bufor o definiowalnej wielkości i flagi. Dzięki zastosowaniu bufora główna pętla nie musi "interesować się" życiem klawiatury - wystarczy jedynie ściągnąć z kolejki klawisz (o ile tam się znajduje). Ponadto takie podejście umożliwia podłączenie dwu lub więcej klawiatur - wystarczy tylko stworzyć dodatkową strukturę i przerobić funkcje tak, by operowały na wskaźnikach zamiast na globalnej strukturze (stworzyłem globalną dla zwiększenia wydajności/wygody).
Co do algorytmu pianina - mikrokontroler generuje proste tony (przebiegi prostokątne) za pomocą wbudowanego sprzętowego timera. W momencie, gdy chcę wygenerować dźwięk, przeliczam wartość docelowej częstotliwości na odpowiednią wartość wpisywaną do rejestru (właściwie rejestrów, bo jest to liczba 2-bajtowa) timera, zależną od częstotliwości taktowania i zmieniam stan wyjścia, do którego podłączony jest głośnik przy każdym przerwaniu.
Pianino posiada własną kolejkę klawiszy - dzięki niej program "pamięta", jakie klawisze są aktualnie wciśnięte i zmienia ton w odpowiedni sposób.
Niestety mając tylko jeden kanał niewiele można zdziałać, ale przy zastosowaniu pewnego triku można nieco urozmaicić dźwięk. Zastosowałem taki sam trik jak w starych DOSowych grach (to były czasy, nie?

Na koniec najciekawsza opcja - nagrywanie sampli. Pozwala ona nagrać 4 sample o długości do 65 nut (w przypadku, gdy wszystkie dźwięki/przerwy są krótsze od 4 sek.). Podczas nagrywania zapisuję w pamięci zdarzenie (wciśnięcie/puszczenie klawisza N) i odstęp od poprzedniego zdarzenia w rozdzielczości około 16ms (1/64) do zajmuje 2B. Jedna nuta to wciśnięcie i puszczenie klawisza. 65*2*2B*4 sample daje 1040B potrzebnej pamięci na sample. oczywiście, można by to bardziej skompresować, ale nie było sensu marnować czasu na pisanie efektywniejszego algorytmu, bo nie taki był cel tego projektu. W przypadku ATMegi8/16 trzeba by zmniejszyć ten obszar o połowę - potrzebna jeszcze miejsca na kolejki, zmienne pomocnicze i stos (no końcu). Sample możnaby też zapisywać na EEPROMie - były by trwałe.
Sample można odtwarzać i jednocześnie grać drugą linię

A teraz najważniejsze - 2 filmiki: na jednym demonstracja działania tryby dwutonowego i sampli na znanej piosence polskiego zespołu a na drugim... marsz turecki

Jeśli będą chętni, to udostępnię kod programu/bibliotekę PS/2 jak tylko ją dokończę i napiszę dokumentację - pisać.
Jak mi się zechce, to dopiszę obsługę myszki - można by modulować nią dodatkowo tony klawiszy (coś na zasadzie wajchy w keyboardach

Jeśli ktoś chciałby się pobawić, to załączam skompilowany program dla ATMegi32 (8MHz). Schemat połączenia (tak jak było mi wygodnie na mojej płytce testowej):
ATMEGA.PORTD.2 (INT0) - PS2.CLK
ATMEGA.PORTC.1 - PS2.DATA
ATMEGA.PORTD.6 - SPEAKER
I oczywiście głośnik do masy, VCC=5V dla atmegi i klawiatury i do tego jakiś elektrokit filtrujący miedzy VCC a GND i kondensatory do kwarcu 8MHZ około 27-30p. Program dodatkowo wysyła dane pomocne w debugowaniu po RS232 i czasem się przywiesi na starcie co jest powodem synchronizacji PS/2, której w bibliotece jeszcze nie ma

Firmware v. 0.1 (alpha):
http://silent.it.cx/files/public/avrpiano/arvpiano_aplha_0_1_m32_8MHz.hex
Sterowanie:
strzałka w górę / w dół - oktawa w górę / w dół
F8 - Tryb jednotonowy
F9 - tryb dwutonowy
F1...F4 - wybór sampla
F12 - rozpoczęcie nagrywania (po sygnale program czeka na wciśnięcie pierwszego klawisza - jeśli chcesz zrobić pauzę na początku, wciśniej przycisk "nie-grający")
ENTER - odtwarzanie sampla
Dolna oktawa - Z ... ","; górna - W...O
Przy okazji zapraszam na moją stronę:
http://silent.it.cx/home/
Cool? Ranking DIY