(* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *)
(*  Soubor: MODULACE.PAS                                                   *)
(*  Obsah: funkce pro prevod retezce do dvojkove soustavy (tedy ordinalnich*)
(*         hodnot jednotlivych znaku) a ukazka FM a MFM modulace binarnich *)
(*         dat pro zapis na magneticka media                               *)
(*  Posledni uprava: ?.?.2005                                              *)
(*  Autor: Mircosoft                                                       *)
(*  Pro kompilaci: nic                                                     *)
(*  Pro spusteni: nic                                                      *)
(*  Upozorneni: tyto zdrojove kody pouzivate na vlastni nebezpeci          *)
(* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *)

function PrevedDoDvojkove(vstup:string):string;
 {parametr Vstup nesmi mit vic nez 31 znaku, jinak se vysledek nevejde do 255
  znaku, coz je max. kapacita typu String, ktery funkce vraci}
var i:byte; {index pro pohyb ve vstupnim retezci}
    j:byte; {index pro pocitani jednotlivych bitu}
    b:byte; {pro ukladani ord. hodnot jednotlivych znaku a jejich zpracovani}
    BinZnak:string[8];{retezec pro ulozeni jednoho znaku ve dvojkove soustave}
    vystup:string; {pomocny retezec, do ktereho se bude ukladat vysledek}
Begin
vystup:='';
binznak[0]:=#8; {ord. cislo nulteho znaku retezce = jeho delka, tak tam takhle
                 nastavime, ze tam bude vzdycky 8 znaku. Dovolit si to muzeme,
                 protoze Binznak je definovan jako string[8], tj. tech 8 znaku
                 se nam tam urcite vejde. Kdyby to byl string[7], uz by to tak
                 neslo. S timto retezcem pak budeme zachazet jako s polem
                 znaku array[0..8] of char (coz taky ve skutecnosti je),
                 protoze to bude jednodussi a rychlejsi nez porad standardne
                 pripojovat jednotlive znaky k retezci. Nastaveni spravneho
                 poctu znaku je nutne, aby pak sel standardne pripojit k
                 vyslednemu retezci (Vystup).}
for i:=1 to length(vstup) do {pro kazdy znak vstupniho retezce}
  begin
  b:=ord(vstup[i]);
   {prevod do dvojkove soustavy (takhle se ve skole obvykle neuci :-) ):}
  for j:=8 downto 1 do  {pro kazdy znak retezce BinZnak od konce, tj. pro
                         kazdy bit prevadeneho cisla}
    if ((b shr (8-j)) and 1) = 1 then binznak[j]:='1'
                                 else binznak[j]:='0';
  {vysvetleni: "X shr Y" znamena "cislo X posunute o Y bitu vpravo" (pokud si
   to predstavujeme tak, ze vpravo mame nejnizsi bit predstavujici cislo 1 a
   vlevo nejvyssi, tedy 8). Posouvame o 8-j bitu, tj. v prvnim kroku o 0, pak
   o 1, o 2 atd. az o 7 (coz bude takova situace, ze se nejvyssi bit posune na
   misto nejnizsiho. Pamatuj si, ze uvnitr pocitace je dvojkove vsechno, takze
   tohle je ta nejjednodussi cesta. "X and Y" da jako vysledek takove cislo,
   ktere vznikne, kdyz s kazdym bitem cisel X a Y udelas logicke AND. Tedy
   1 and 1 = 1, vsechno ostatni 0. Vyraz "X and 1" tedy zpusobi, ze vsechny
   bity cisla X krome toho nejnizsiho ("nejvic vpravo") se vynuluji a v tom
   nejnizsim zustane to, co tam bylo puvodne (1 and 1 = 1, 0 and 1 = 0).
   Testujeme tedy bity ordinalniho cisla smerem od nejnizsiho k nejvyssimu,
   tedy "zprava doleva", a se stejnou orientaci (od konce, tj. taky zprava)
   je zapisujeme ve forme znaku '0' a '1' do retezce BinZnak.}
  {ted je hotovy prevod jednoho znaku, zapiseme ho do vysledku:}
  vystup:=vystup+binznak;
  end;
preveddodvojkove:=vystup; {odeslani navratove hodnoty funkce}
End;{preveddodvojkove}


{Par slov o modulaci.
Kdyz chceme neco zapsat treba na harddisk, neda se psat stylem 1 = impuls,
0 = pauza, protoze pri delsi posloupnosti nul by disk ztratil synchronizaci
a nevedel by, kolik nul uz ubehlo. Proto se data moduluji jinak, napr.
nejjednoduseji treba takhle - FM modulace:}

function FM(vstup:string):string;
 {max. delka vstupu je 127 znaku}
var i:byte;
    vystup:string;
Begin
vystup:='';
for i:=1 to length(vstup) do if vstup[i]='1' then vystup:=vystup+'PP'
                                             else vystup:=vystup+'PN';
fm:=vystup;
End;{FM}

{P znamena impuls, N pauza. Protoze ale impulsy zabiraji na mediu vic mista
nez pauzy, snazime se, aby jich bylo pokud mozno co nejmin (ale zase ne moc
za sebou). Treba MFM modulaci:}

function MFM(vstup:string):string;
 {max. delka vstupu je opet 127 znaku}
var i:byte;
    vystup:string;
Begin
vystup:='';
for i:=1 to length(vstup) do
  if vstup[i]='1' then vystup:=vystup+'NP'
                  else if (i=1)or(vstup[i-1]='0') then vystup:=vystup+'PN'
                                                  else vystup:=vystup+'NN';
mfm:=vystup;
End;{mfm}

{tady zacina ukazkovy program:}

var Retezec,RetezecDvojkovy,RetezecZmodulovany:string;

BEGIN
writeln('Vita vas program pro demonstraci FM a MFM modulace dat.');
writeln('   (c) Mircosoft 2005');
writeln;
write('Zadej retezec k zakodovani (max. 15 znaku!): ');
readln(retezec);
RetezecDvojkovy:=PrevedDoDvojkove(retezec);
writeln('Ve dvojkove soustave by to bylo: ',RetezecDvojkovy);
writeln('Stiskni Enter...');
readln;
RetezecZmodulovany:=FM(RetezecDvojkovy);
writeln('Po FM modulaci to dopadne takhle: ',RetezecZmodulovany);
writeln('Opet Enter...');
readln;
RetezecZmodulovany:=MFM(RetezecDvojkovy);
writeln('A po MFM modulaci: ',RetezecZmodulovany);
writeln('A jeste jednou Enter a to uz bude vazne vsechno...');
readln;
END.

{Vlastni vypocty jsou prakticky na trech radcich (volani tech funkci), cely
zbytek je jenom omacka pro uzivatele.

Jeste vic by se program zjednodusil, kdyby se vynechalo prevadeni cisel na
retezec jednicek a nul a PNPN by se tahalo rovnou ze vstupniho retezce.
Plus jeste asm, lodsb, shr, jc ..., ale to uz by bylo moc lehke, ze jo :-) }
