Poniżej opis prostego przydasia umożliwiającego konwersję plików wynikowych Intel Hex do formatu WAV, które możemy potem odegrać kartą dźwiękową naszemu CA80 niczym z magnetofonu. Programik konwertuje nie tylko surowe dane z pliku *.hex, potrafi też spreparować dla CA80 rekord EOF o zadanych cechach. Dokładne parametry transmisyjne CA80 (czułość, zdolność detekcji sygnału nośnego, etc/itd) są sprawą indywidualną danego egzemplarza komputera, stąd kilka parametrów sygnału można ustalić na etapie konwersji, minimializując ryzyko błędnego wczytywania.
-- ♠ --
❦ hex2wav - kompilacja
Pliki źródłowe oczywiście na GitHub ⇨ hex2wav, z mojej strony słowa uznania dla autorów mini-biblioteki ⇨ wavfile na bazie której powstała ta pocieszna aplikacja. Kompilacja pod Linux jest trywialna i sprowadza się sklonowania repozytorium, a następnie do:
gcc hex2wav.c wavfile.c -o hex2wav -lm
Powstały plik hex2wav dobrze umieścić gdzieś w folderze objętym zmienną PATH, będzie zawsze pod ręką.
❦ hex2wav - parametry
Na początek akapitu odeślę do tomiku MIK05, do rozdziału 1.9 Współpraca CA80 z magnetofonem tam znajdziemy wszelkie teoretyczne wyjaśnienia na temat kodowania sygnału i jego parametrów. A tu zaprezentuję tylko te cechy, na którem mamy wpływ z linii poleceń i wyjaśnię - skąd taka potrzeba. Wywołanie hex2wav w formie ogólnej przedstawia się następująco:
-i input_file - wejściowy plik w formacie Intel Hex o rozmiarze rekordów 16 lub 32 bajty; nazwę pliku podajemy, gdy konwertujemy *.hex, gdy chcemy utworzyć dźwiękowy obraz samego rekordu EOF nie jest ona konieczna
-n NN - określa dwucyfrową (w hex) nazwę/identyfikator zbioru, parametr jest obowiązkowy zarówno dla konwersji z *.hex jak i podczas kreowania rekordu EOF
-e AAAA - określa czterocyfrowy (w hex) adres wejścia do programu w rekordzie EOF; jest opcjonalny podczas konwersji z *.hex - gdy go nie podamy rekord EOF nie zostanie dopisany do materiału audio; adres AAAA jest obowiązkowy gdy nie podamy nazwy pliku wejściowego ponieważ program zakłada wtedy tylko i wyłacznie generację EOF-a, tam adres jest podstawowym parametrem; gdy planujemy ładować programy w locie procedura OMAG/0x071B, to można rozważyć podawanie jako AAAA wartości (adresu) procedury SPEC/0x0065 zawierającej rozkaz ret; mechanizm OMAG załaduje dane, wykona skok zgodnie z adresem wejścia czyli finalnie przez SPEC zawróci sterowanie do programu głównego, bez wykonania załadowanego kodu; podanie jako AAAA wartości od czapki może skutkować pójściem CA80 w maliny, to oczywiste.
-m MM - określa wartość prędkości transmisji podczas współpracy z magnetofonem, w tym przypadku jest to ilość efektywnych bitów danych na sekundę kodowanych w Manchester do materiału audio; operujemy wartociami z MIK05 czyli odpowiednio: 15 to 240 bitów/sek (szybka, błędogenna transmisja), 25 oznacza 140 bitów/sek i jest wartością domyślną 35 to 100 bitów na sekunde, ślamazarnie, ale za to z dużą odpornością na zakłócenia; podanie innych niż 15/25/35 wartości jest przez programik kodujący ignorowane;
-s SS - definiuje ilość bajtów synchronizacji (o wartości 0x00) poprzedzających rekord danych (zaczynający się sekwencją 0xFD,0xE2); bajty synchronizacji są odczytywane (via RBYT) i pomijane w procedurze OMAG aż do chwili znalezienia znacznika rekordu, stąd dobrze jest zostawić choć kilka (sensownie min.2) aby CA80 miał szansę 'zaskoczyć'; detale OMAG i tego procesu to tomik MIK08 od strony 1-41, polecam w wolnej chwili
-f FREQ - parametr ustawiający częstotliwość sygnału nośnego, który podlega kodowaniu Manchesterem; domyślna wartośc to 3.5 kHz ponieważ taka wartością operuje poprawnie zbudowany i wyregulowany interfejs magnetofonowy przy zapisie i odczycie; jak łatwo zgadnąć w praktyce jest różnie, więc dodałam parametr pozwalający dostroić podawany sygnał do kaprysów naszego egzemplarza CA80, sensowne wartości są z przedziału od około 2.8 kHz do 4 kHz, zależnie jak nam się polutował układ odczytujący.
-o output_file - wynikowy plik *.wav, na stałe wbita jest częstotliwość próbkowania audio - 44.1 kHz, sygnał jest monofoniczny (jeden kanał)
-v - opcja verbose, czyli tryb gadatliwy, wypisuje na terminal zarówno podsumowanie ustawień konwersji jak i sekwencje kodowanych bajtów
❦ hex2wav - konwersja
Nie będe tu wypisywała wszelkich możliwych wariantów uruchomienia aplikacji, może tylko kilka codziennych i raczej typowych zastosowań:
generowanie audio dla programu lub danych, bez rekordu EOF
program o nazwie 0x55 do odcztu z typowymi (zainicjowanymi via [7][=]) parametrami transmisji, załadowanie zleceniem [6][55][=], uruchomienie [G][C000][=]
generowanie audio dla programu i jego rekordu EOF - rekordy 32 bajtowe (lub o zmiennej długości)
program o nazwie 0xFF do odcztu z typowymi (zainicjowanymi via [7][=]) parametrami transmisji, załadowanie zleceniem [6][FF][=]
plik *.hex to wynik pracy linkera z pakietu SDCC, przed obróbką przez packihx skracającym rekordy do 16 bajtów
program o nazwie 0x55 do pooowolnego odcztu (zainicjowanie transmisji 100 bit/sek via [7][3510][=]), skrócona do minimum sekwencja synchronizacji, załadowanie zleceniem [6][55][=], uruchomienie [G][=]
hex2wav, simple CA80 hex to audio converter, tasza (c) 2019
input file name: print_LOAD.hex
program ID : 55
EOF address : C000
tape bit rate : 100
synch seq. len : 2
carrier freq. : 3500 (by default)
samples per bit: 441
samples total : 523908
output file : print_LOAD.55.slow35.synch2.prg.eof.wav
00 00
FD E2 55 10 00 C0 DB 31 66 FF 21 0C C0 CD D4 01 80 18 FE 38 5C 77 5E DC
FD E2 55 05 10 C0 D6 40 23 1C 40 FF 42
00 00
FD E2 55 00 00 C0 EB
Done.
Materiał audio: ⇨ print_LOAD.55.slow35.synch2.prg.eof.wav
Zwróćmy uwagę na wyliczoną wartość `samples per bit` - 441 względem poprzednich 315 dla szybkości 140 bitów/sek.
Zmniejszenie szybkości transmisji magnetofonowej zwiększa objętość materiału audio (samples total), zwiększenie - powoduje, że materiał jest krótszy.
zmiana częstotliwości sygnału nośnego
a. program o nazwie 0x28 do odcztu z typowymi (zainicjowanymi via [7][=]) parametrami transmisji, nośna 2.8 kHz
Porównianie widm wyliczonych przez Audacity, okno Hanninga na 128 próbek.
Zmiana częstotliwości nośniej nie wpływa na rozmiar wynikowego materiału audio.
I kończąc ten wątek - bardzo proszę nie traktować obecności tego parametru jako obejścia badziewnie zestrojonego układu obsługi magnetofonu. Jeżeli programy nie wczytują się do CA80 na standardowej szybkości 140 bitów/sek (zainicjowanej [7][=]) to naprawdę mamy problem, zatem próbnik logiczny w dłoń i szukamy błedu w układzie.
❦ hex2wav - obróbka końcowa
Generowane pliki *.wav mogą być naprawdę zacnych rozmiarów, niech za przykład posłuży konwersja testowego wsadu ⇨ 8kb_8000.hex to pliczek hex niosący 8192 bajty surowych danych. Jego przetworzenie na audio ze standardowymi ustawieniami i rekordem EOF
da plik 8kb_8000.wav o rozmiarze około 86MB! Troszkę jakby dużo, każdy zauważy. I dlatego można się pokusić o spreparowanie z wav pliku *.mp3, wprawdzie ten format jest kompresją stratną i wnosi drobne zniekształacenia, ale cyt. `jak doświadczalnie stwierdzono` pliki *.mp3 całkiem dobrze wczytują się do CA80 na typowych ustawieniach. Sama konwersja pod Linux wygląda następująco:
Dla ciekawości możemy zerknąć na przykładowe przebiegi, widać zniekształcenia, ale tak na oko (i w praktyce) nie wnoszą one zaburzeń w procesie odczytu.
Wynikowy plik 8kb_8000.mp3 ma już `tylko` 23MB i otwiera pole do eksperymentów z konwersją via ffmpeg to znaczy - szybkością strumienia (tu:192kb/s) czy rozmiarem próbek, proszę znaleźć optimum dla swojej karty dźwiękowej i osobistego CA80.
❦ hex2wav - odtwarzanie plików / ładowanie do CA80
Tu, choć zagadnienie niby proste - jest kilka zdań do napisania. Jeżeli ktoś jest z gatunku okienkowych, plik czy to *.wav czy *.mp3 można odegrać praktycznie dowolnym odtwarzaczem, wejście magnetofonowe CA80 podłączamy do wyjścia słuchawkowego karty dźwiękowej do wybranego kanału lub spreparowanym wtykiem Jack 3.5 mm ze zwartymi L+P (sprzętowe mono). Pewnych eksperymentów może wymagać ustawienie poziomu głośności, tu nie ma porady innej niż seria prób, aż uzyskamy bezbłędne załadowanie dłuższego niż kilkaset bajtów zbioru. Problem powstanie z zapamiętaniem jakie ustawiliśmy sobie suwakami w okienkach parametry, no cóż - to ta niemiła strona GUI.
Ja ze swej strony proponuję odtwarzanie wsadowe, z konsoli. Dla Linux przygotowano wiele różnych programów manipulujących strumieniami audio z linii poleceń, do odtwarzania doskonale nadaje się na przykład programik sox z pakietu SoX(Sound eXchange). Materiał w formacie *.wav odtwarza bez miałczenia zaraz po instalacji, jeżeli checmy grać pliki *.mp3, to proszę doinstalować pakiet libsox-fmt-all. Pewną zachwostką może być określenie na której karcie dźwiękowej chcemy pracować z CA80, to szczególnie w przypadku gdy mamy więcej niż jedną. U mnie do takich zabaw oddelegowana została osobna (na PCI) tania karta, sztuka polega na odgrywaniu nią właśnie plików dla CA80, nie robiąc zamieszania w grającej na wzmacniaczu muzyce, a więc - lista kart dźwiękowych w naszym komputerze:
Programik pacmd (z pakietu pulseaudio-utils) wylistuje nam bieżące aktywne wyjścia, oznaczy też gwiazdką to domyślne, u mnie akurat to karta wbudowana w płyte główną, do muzyki. Wykonanie dla odmiany polecenia
pokaże wszystko z kompuera mające związek z audio, po odrzuceniu grajka Intela (płyta), NVIDIA (HDMI karty graficznej) oraz tunera TV od Brooktree - pozostaje `04:00.0 Multimedia audio controller: Creative Labs CA0106/CA0111 [SB Live!/Audigy/X-Fi Series]` co jest zbieżne z drugim wyświetlonym przez pacmd wpisem. Czyli zidentyfikowaliśmy urządzenie, do wyjścia którego można podłączyć CA80! A zatem:
W przypadku tego pliku - 8kB danych ładuje się do CA80 nieco ponad kwadrans, niektórzy zapewne przypomną sobie stare dobre czasy Commodore C64. No i oczywiście jak źle zidentyfikujemy kanały dźwiękowe to cały pisk pójdzie w głośniki, mamy spore szanse na szybkie wypisanie z rodziny, proszę zatem uważać z głośnością.
BTW głośności - tryb odtwarzania sox ma jak widać powyżej parametr -v, to od volume, z parametrami >1 jest głośniej, z <1 ciszej, a głośność należy dobrać sobie eksperymentalnie, zależnie od parametrów całej instalacji.
Na koniec opowieści - konwersja i ładowanie programów na żywo. Najpierw wspomniany wcześniej plik nmi_spy_1.hex, linker SDCC przygotował hex tak jak przygotował, niemniej jednak program daje się przetworzyć i załadować do CA80. I nawet po wykonaniu *G coś tam na wyświetlaczu się pokazuje, snać kod sprawia wrażenie działania, a przynajmniej się stara.
Drugi programik to dawca zdjęcia tytułowego - print_LOAD.hex. Teraz na żywo widzimy kolejno - konwersję, załadunek oraz z racji dołożonego EOF-a - błyskawiczne uruchomienie.