Perceptrons or two daughters of cybernetics

Noriu pasidalinti įdomia citata, kurią radau “Connectionsism and the Mind” W.Bechtel and A.Abrahamsen knygoje:

Once upon a time two daughter sciences were born to the new science of cybernetics.
One sister was natural, with features inherited from the study of the brain, from the way nature does things. The other was artificial, related from the beginning to the use of computers. Each of the sister sciences tried to build models of intelligence, but from very different materials. The natural sister built models (called neural networks) out of mathematically purified neurones. The artificial sister build her models out of computer programs.
In their first bloom of youth the two were equally successful and equally pursued by suitors from other fields of knowledge. They got on vert well together. Their relatioship changed in the early sixties when a new monarch appeared, one with the largest coffers ever seen in the kingdom of the sciences: Lord DARPA, the Defence Department’s Advanced Research Projects Agency. The artificial sister grew jealous and was determined to keep for herself the access to Lord DARPA’s research funds. The natural sister would have to be slain.
The bloody work was attempted by two staunch followers of the artificial sister, Marvin Minsky and Seymour Papert, cast in the role of the huntsman sent to slay Snow White and bring back her heart as proff of the deed. Their weapon was not the dagger but the mightier pen, from witch came a book – Perceptrons …

x51 architektūros assembleris #1

Įvadas

Turbūt ir nereikia sakyti, jog assembleris šiuo metu nėra pati populiariausia programavimo kalba. Tačiau, kuomet iš įterptinės sistemos reikalaujama mažos kainos, tuomet kiekvienas bitas yra aukso vertas. Tokiu atveju assemblerio žinios labai pagelbės. Šiame straipsnyje pabandysiu trumpai apžvelgti esminius kirčius intel x51 architektūros ( 8051 ) mikrokontrolerio assemblerio programavime. Originalus procesorius yra 8bit. Yra išleistos ir 16bit versijos, tačiau remsimės originalu.

Emuliatorius

Dirbant Linux platformoje susiduriama su emuliatoriaus problema, kadangi jų nėra daug:

  • SDCC – Small Device C Compiler. Dirba tik su C kalba. Assemblerio nepalaiko.
  • Emu51. Susipažinti taip ir neteko. Kompiliavimo problemos. Paskutinis source atnaujinimas buvo 2004 metais. Jo naudoti nerekomenduojama.
  • Jeigu jaučiatės labai sėkmingi, galite pabandyti cereal.
  • Pats apsistojau ir Jums taip pat rekomenduoju mcu8051ide. Pastarasis palaiko tiek assemblerį, tiek C programavimo kalbas. Turi puikius informacinius blokus. Galima step-by-step stebėti kaip vyksta visas procesas ir on-fly keisti visus duomenis.

Jeigu naudojate Arch Linux, mcu8051ide įdiegimas bus gan paprastas:

yaourt -S mcu8051ide

Projektas yra prižiūrimas, tad kompiliavimo metu bėdų iškilti neturėtų. Jeigu iškyla kažkokios problemos, rašykite man arba į AUR’ą.

Registrai, vėliavos ir portai

Jeigu įdiegimas ( kompiliavimas ) praėjo sėkmingai, tuomet turėtumėt matyti kažkokį panašų vaizdą

mcu8051ideViršutinis menu yra klasiškas. Galima susiemuliuoti kažkokius papildomus įrenginius: LED panel, LED display ir kt.

Pagal numatytus nustatymus dešinėje rodys registrų reikšmes.Reigstrai – tai realiai kažkokie atminties bloko “greitukai”, t.y. registrais galima greitai pasiekti tam tikros vidinės atminties skaičių. Taip pat egzistuoja “registrų bankai”. Pagal numatytus nustatymus registro bankas bus nustatytas ties “0” reikšme, o tai reiškia, jog registras R0 rodys į 0x00 atminties vietą, R7 rodys į 0x07 atminties vietą.

Be registrų yra dar daug visokių įdomybių:

idomybėsKairėje yra vidinė atmintis – atminties blokai, suskirstyti į 8 stulpelius. Paskui seka A ir B raidės. A raidė vaidina “accumulator”. Tai labai geras, greitas 8bit atminties skyrius, per kurį, realiai visos operacijos ir atliekamos. Dar yra B “accumulator”, tačiau jis naudojamas tik dalybai ir sandaugai.

Žemiau seka PSW ( Special Status Word ) kitaip dar vadinami “vėliavomis” – tai vieno bito ilgio kintamieji ( jeigu juos galima pavadinti kintamaisiais.. ) Realiai tai yra adreso trumpinimo simboliai, kurie nurodo būtent į tam tikrą atminties vietą. Tarkim C ( Carry ( apie jį dar pašnekėsim ) ) direktina į 0xD7 atminties vietą, tai visai nebūtina naudoti C, norint pasiekti Carry flag.

Toliau seka Taimeriai, Interuptai, bet į juos nesigilinsim. Apie juos reikia rašyti atskirą straipsnį.

P0, P1, P2, P3 – yra virtualūs portai. Simuliacijos metu galima pakeisti jų reikšmes ir surežisuoti visus galimus signalus į portus;

Pažaidimas: 16bit aritmetika 8bit mikrokontroleryje

Parašykime kokia sunkią programą. Daug žadanti pradžia, argi ne? Tarkim susidūrėme su gan plačia, bet išsprendžiama problema – 16bit aritmetika 8bit mikrokontroleryje.

Turim du kintamuosius: vienas 0x1234, kitas 0x43FF. Nors abudu skaičiai yra 16bit ilgio, tačiau mes vieną skaičių galime išskaidyti į du skaičius, kurių ilgis 8bit‘ai. Taigi, šiuo atvėju 0x1234 bus 0x12 ir 0x34, o 0x43FF bus 0x43 ir 0xFF. Sekantys skaičių skaičiai ( kaip painu.. ) turi net savo pavadinimą! Pavyzdžiui skaičiaus 0x1234, 0x12 yra MSB ( Most Significant Bit ), 0x34 yra LSB ( Least Significant Bit ). MSB galima suprasti kaip kairiausią skaičiaus dalį, o LSB kaip dešiniausią skaičiaus dalį. Sudėtingesnėse ( 32bit ) operacijose tarp MSB ir LSB atsiranda dar du papildomi blokai, kurių pavadinimų nežinau, bet painiavos užtenka. Norint sudėti šiuos du kintamuosius, sudėti reiks atlikinėti keliais etapais.

Čia ne C, kad tiesiog parašai pliuso ženklą prie kintamojo ir viską už tave padaro kompiuteris..

Mūsų kodas:

	.ORG 0H		; program start address

	MOV R2, #12H	; #1234H MSB
	MOV R3, #34H	; #1234H LSB
	MOV R4, #43H	; #43FFH MSB
	MOV R5, #0FFH	; #43FFH LSB

	MOV A, R3	; #34H
	ADD A, R5	; #34H + #FFH
	MOV R7, A	; saving LSB
	MOV A, R2	; #12H
	ADDC A, R4	; #12H + 43H + C
	MOV R6, A	; saving MSB

	.END		; collect our toys and go home
  1. ORG pasako kur turi būti programos pradžios adresas. Šiuo metu, kadangi nėra naudojami interuptai ir taimeriai, tai mes programą galime pradėti nuo pačios pirmos ( nulinės ) eilutės.
  2. MOV duomenų perkėlėjas. Jis kaip nešikas – jam pasakai ką perkelti – jis tai ir perkelia.
  3. ADD yra sumos komanda. Sumą būtina daryti per “accumulator”.
  4. ADDC yra sumos komanda, kuri sudeda tris “kintamuosius” ( galvojant C kalba ). Pirmasis kintamasis yra Carry flag/C ( tuoj jį aptarsim ), antrasis yra “accumulator”, o trečiasis gali būti tiek registras, tiek adresas į reikšmę, tiek tiesioginė reikšmė.

Keli paaiškinimai:

  1. .ORG 0H eilutėje, 0H parašytas taip, nes jis nusako adresą.
  2. MOV R2, #12H eilutėje #12H parašytas taip, nes jis nusako konkrečią reikšmę. Šiuo atvėju tai 0x12 arba 18 dešimtainėje skaičiavimo sistemoje ( 0x12 = #12H = #18D ).

Spaudžiam compile ir run. Emuliatorius turėtų užlockinti kodą ir iškarto rodyti sumuliavimo aplinką.

simuliavimas

Skirtumas nuo praeito paveiksliuko – dabar viskas aktyvu ( iš pilkos spalvos patapo žymiai spalvingesniu ). Navigacija atliekama su sekančiais mygtukais:

navigacija

  1. Raudonas mygtukas stabdo simuliaciją;
  2. Baltas mygtukas perkrauna simuliaciją;
  3. Rodyklę gražina viską viena kodo eilute prieš tai;
  4. Dvi pėdukės paleidžia vieną kodo eilutę;
  5. Dvi pėdukės su žaliu taškeliu – peršoka vieną kodo eilutę;
  6. Play mygtukas animuoja visą kodą ( stebuklų nesitikėkite );
  7. Ir paskutinis mygtukas paleidžia visą kodą, o rezultatus parodo paskui;

Dabar galime paspaudinėti dvi pėdukes ( be taškelio ) ir stebėti kaip viskas keičiasi. Ties 7 eilute rezultatas turėtų būti toks:

registru_operacijosRaudonai pažymėtuose vietose ( taip, tai mūsų vidinė atmintis ) ties x2, x3, x4 ir x5 atsirado skaičiukai! Nuostabu tai, kad jie visiškai sutampa su mūsų nusakytais skaičiukais viršutinėse kodo eilutėse! Vadinasi, viskas tvarkoje. Toliau jau prasideda bitų operacijos.

  1. Įkeliam į A pirmąją reikšmę, 0x34 ( taip, sumavimą pradedame nuo LSB ):
    34_i_lsb A pakeitė savo reikšmę iš 0x00 į 0x34! Taip pat žaliai nusišvietė P vėliava ( P yra parity flag, – ji parodo kuomet 1 ir 0 kiekis yra nevienodas ).
  2. Sumuojam 0x34 su 0xFF:
    stebuklaiČia jau prasideda stebuklai.
    Sudedant 0x34 su 0xFF gauname kiek? Gauname 0x133, tačiau, juk 0x133 reikalauja 9bitų!
    Į pagalbą ateina pažaliavęs Carry flag. Jis yra vieno bito ilgio ir pažaliuoja tuomet, kuomet suma ( arba atmintis ) viršija 8bit ribą. Kodėl C tik 1 bit ilgio? Nes tik tiek ir užtenka. Jeigu sudėti du didžiausius 8bit skaičius, 0xFF, mes gausime 0x1FE ir tam užtenka 9bitų.
  3. Saugom mūsų gautą atsakymą į R7 registrą:
    saugom rezultatąCarry flag vis dar žalias.
  4. Perkeliam į A 0x12 ir sumuojam 0x12 su 0x43 ir Carry flag, kurio reikšmė 0x1:
    jau i pabaigąKaip matome, Carry flag vėl tapo raudonas. Tai reiškia, kad dabar jo vertė yra lygi 0x0. Carry flag visuomet nusimeta, kuomet yra naudojama operacija ADDC.
  5. Išsaugom mūsų skaičiumi ir džiaugiamės gautu atsakymu:
    jau atsakymas

Atsakymą gavom 0x56 MSB ir 0x33 LSB, t.y. 0x5633. Jeigu patikrinsite su skaičiuotuvu arba wolframalpha – gausite tą patį.

Išvados

Tikiuosi per daug painiavos neįvėliau į Jūsų supratimą apie assemblerį. Šis straipsnis yra tik įvadas. Vėliau papasakosiu apie bitų operacijas, jų stumdymą, loop’us, disassemblerį, interupt’us ir timer’ius.

Analizuojam signalus su python

Matlab DIE !!!

Taikyti python kasdieniams skaičiavimas pradėjau visai neseniai. Ankščiau mane labai tenkino ir octave ar calc ar maxima. Tačiau dabar, kai duomenų srauto atvaizdavimo poreikis kyla vis labiau, tenka ieškoti kitų galimų įrankių.

Pirma man atėjusi mintis ( kaip visad pirmosios mintys turi būti neteisingos ) buvo tiesiog pradėti rašyti savo programinį paketą. Tai užimtų amžius, bet galiausiai, pabaigoje turėčiau naudojamą įrankį.

Laiko stoka ir į pagalba tiesiog atėjo mano mylimas python! O su juo analizuoti signalus yra tikrai lengva panaudojus tiesiog vieną cmath modulį.

Ilgai nelaukiant, paimkime paprastą pavyzdį – neperiodinį, nesimetrinį signalą su faze. Tarkim mūsų signalas sklinda nuo 0 iki tau. Tuomet spektrinės analizės formulė atrodys

V(f) = A/(-i*2*pi*f)*(e**(-i*2*pi*f) -1)

Tikiuosi kas nors atpažįstate spektrinės analizės formą.

Kadangi dabar turim galutinę formulės formą, galima pradėti skaičiavimus! Paimkime amplitudę Atau = 2 V.

def result( f ):
  from cmath import pi, e, sqrt, polar
  A = 2. # 2V
  i = sqrt(-1)
  try:
    r, phi = polar ( A/(-i*2.*pi*f)*(e**(-i*2*pi*f) - 1) )
    return r, phi
  except ZeroDivisionError:
    return A, 0

Klaidos tikrinimą reikia daryti neatsitiktinai, o tikslingai, kadangi kai dažnis pasiekia nulį, mes turim dalinimą iš nulio, o tai sąlygoją klaidą. Kaip žinoma, funkcijos python gali gražinti keletą kintamųjų iškarto ir šiuo atvėju mums tai labai pagelbėja ( nors dirbančioje programoje turėjau išskaldyti r ir phi, dėl klaidos ).

Dabar teliko parašyti pagrindinę funkciją, kuri kreipiasi į mūsų parašytą ankstesnę funkciją.

def main():
  f = open("phase_shift_amplitude.dat", "w") # duomenu failas
  p = open("phase_shift_phase.dat", "w") # duomenu failas
  for fr in [x*0.001 for x in range(-3000,3001)]:
    r, phi = result(fr)
    print >>f, fr, r
    print >>p, fr, p

Galutinis, veikiantis variantas atrodo taip

#!/usr/bin/env python
def result ( f ):
  from cmath import pi, sqrt, polar
  A = 2. # 2V
  i = sqrt(-1)
  try:
    r, phi = polar ( A/(-i*2.*pi*f)*(e**(-i*2.*pi*f) - 1))
    return r
  except ZeroDivisionError:
    return A

def phiesult ( f ):
  from cmath import pi, e, sqrt, polar
  A = 2. # 2V
  i = sqrt(-1)
  try:
    r, phi = polar ( A/(-i*2.*pi*f)*(e**(-i*2.*pi*f) - 1))
    return phi
  except ZeroDivisionError:
    return 0

def main():
  import math
  f = open("phase_shift_amplitude.dat", "w") # duomenu failas
  p = open("phase_shift_phase.dat", "w") # duomenu failas
  for fr in [x*0.001 for x in range(-3000,3001)]:
    r = result(fr)
    phi = phiesult(fr)
    print >>f, fr, r
    print >>p, fr, phi

if __name__ == '__main__':
  main()

Dabar mes turime du failus su amplitudės ir fazės ( radianais ) skaitinėm vertėm. Teliko tik juos atvaizduoti. Tam galime pasitelkti gnuplot:

plot 'phase_shift_amplitude.dat' smooth frequency

plot 'phase_shift_phase.dat' smooth frequency

Arba LaTeX su pgfplots:

\begin{tikzpicture}
  \begin{axis} [
    width=500pt,
    height=230pt,
    grid=major,
    ylabel={$|V(f)|$},
    xlabel={$f, Hz$}
    ]
    \addplot[black] file {phase_shift_amplitude.dat};
  \end{axis}
\end{tikzpicture}\\
\textsl{Figure 1. Signal, with phase shift, amplitude spectrum.}\\

\begin{tikzpicture}
  \begin{axis} [
    width=500pt,
    height=230pt,
    grid=major,
    ylabel={$argV(f)$},
    xlabel={$f, Hz$}
    ]
    \addplot[black] file {phase_shift_phase.dat};
  \end{axis}
\end{tikzpicture}\\
\textsl{Figure 2. Signal phase, with phase shift.}\\

Asmeniškai aš daugiau esu linkęs prie Latex su pgfplots. Gnuplot labai geras įrankis greitam duomenų pateikimui. O jau atsakaitai geriausias įrankis yra LaTeX ( tikrų vyrų dokumentų tvarkyklė! ).