[AD2][Pascal] Digital I/O - ROM Mode | przerzutnik RS i dekoder do rosyjskiej VFD | WaveForms SDK | cz.4

Tutaj umieszczamy tematy związane z językami programowania niepasującymi do innych działów.
Regulamin forum
Temat prosimy poprzedzić nazwą języka umieszczonego w nawiasach kwadratowych np. [Pascal].
Awatar użytkownika
tasza
Expert
Expert
Posty: 901
Rejestracja: czwartek 12 sty 2017, 10:24
Kontaktowanie:

[AD2][Pascal] Digital I/O - ROM Mode | przerzutnik RS i dekoder do rosyjskiej VFD | WaveForms SDK | cz.4

Postautor: tasza » wtorek 08 sty 2019, 15:55

♬ ☘ Moja muzyka do kodowania ♬ ♬ ♬ ☘
♫ ♩ ♪ Dawn Of Solace ⚡ ☘ ⚡ z albumu The Darkness - I Was Never There♪ ♩ ♫
https://youtu.be/gTc-nyyvvMI



Kolejny odcinek opowieści o SDK do Analog Discovery 2 będzie nieco zakręcony. Blok cyfrowych wejść i wyjść jak już z pewnością zauważyliśmy pełen jest ciekawych funkcjonalności. Są też takie, których egzotyka nieco onieśmiela i na pierwszy rzut oka nie bardzo wiadomo, co z nimi w ogóle zrobić. Pomysły pojawiają się wraz z kolejnymi eksperymentami i o tym będzie dalej.

Jazda w trybie ROM

Na egzaminie na prawo jazdy pytają blondynkę: proszę opowiedzieć jak działa silnik w samochodzie.
A mogę swoimi słowami? Może pani! Brum brum brum.


Tym oto oklepanym tekstem chcę zasygnalizować pewną trudność w ogarnięciu i wytłumaczeniu działania bloku Digital I/O w ROM. Bo to jest tak: bezpośrednie sterowanie cyfrowymi wyjściami AD2 jest intuicyjnie jasne, podobnie jak odczyt ich wartości. Odtworzenie zapisanego wzorca bitowego na zestawie wyjść (BUS) też nie jest jakoś zaskakujące - kolejne kombinacje bitów są wystawiane na wyjścia AD2 zgodnie z ich położeniem w podręcznej pamięci, a ta adresowana jest stosownie taktowanym licznikiem. Od ustawień licznika - wartości minimalnej i maksymalnej oraz częstotliwości taktowania zależą parametry czasowe wyjściowego przebiegu. I to, nawet w takich ogólnikach jest w miarę jasne, więcej informacji oczywiście w dokumentacji AD2: :arrow: https://reference.digilentinc.com/wavef ... _generator

Państwo sympatyczni z Digilent poszli dalej w fantazjach i pomyśleli mniej więcej tak:
skoro mamy zapisany wzorzec bitowy w pamięci adresowalnej wewnętrznie sterowanym licznikiem, to co by było gdyby linie adresowe tej pamięci udostępnić także i na zewnątrz, kojarząc z wejściami AD2? Czyli pamięć adresować nie licznikiem ale słowem sterującym z zewnątrz? No i właśnie na tym polega tytułowa sztuczka trybu ROM - przy pomocy stosownej kombinacji logicznej na wejściach wybieramy wskazywany nią wzorzec z pamięci AD2. I stąd nazwa ROM - bo taka jest właśnie idea działania pamięci Read Only Memory. Oczywiście to tylko analogia koncepcji - w przypadku AD2 jesteśmy mocno ograniczeni aspektami fizycznymi magicznego pudełeczka - ilością wejść/wyjść. Tych jak wiadomo jest razem 16, podczas definiowania wzorców musimy z tego wygospodarować i linie wyjściowe i wejściowe-adresowe naszej "pamięci". Jako linie adresowe pracują kolejno delegowane wejścia DIO-0,DIO-1 itd. Wyjścia układu najlepiej (w/g mnie) delegować od końca, od DIO-15 w dół. No i teraz kluczowe chyba spostrzeżenie - to daje możliwość zdefiniowania przy pomocy AD2 prawie dowolnego układu kombinacyjnego (prawie, bo mamy limit na I/O), a kombinacyjnego - bo wyjścia zależą tylko od bieżącego stanu wejść i tabeli prawdy podanej w konfiguracji.

Bramka XOR

Na początek postanowiłam zbudować jedną, prosta brameczkę - padło na XOR, w sumie nie wiem czemu...
Układ na płytce stykowej prymitywny bardzo:

00_xor.jpg


Oczywiście najpierw test podłączenia LED na DIO-0,DIO-1 oraz DIO-15, aby była pewność że ewentualne błędne działanie to sprawa konfiguracji puderniczki AD2 a nie drucików.

https://youtu.be/1LJoh-E4ryQ

Kolejny filmik, to przygotowanie rzeczonej bramki XOR w programie WaveForms - widzimy dokładnie jak buduje się tabele prawdy elementu.

https://youtu.be/Gz1btzUeKN0

Czas odpowiedzi bramki zależnie od częstotliwości taktowania bloku - pokazuje to filmik:

https://youtu.be/7tdgVQvHupY

Oscylogramy, dla różnych wartości dzielnika którymi traktujemy wzorcowe 100MHz zbiera rysunek:

01_xor_delay.png


Widać całkiem wyraźnie że czas odpowiedzi układu silnie zależy od częstotliwości taktowania - mamy w ten sposób pewną kontrolę nad czasem propagacji tak udawanej bramki. I jeszcze dwa filmiki, na których możemy porównać wyjściowe przebiegi i ich stabilność na osi czasu względem wejścia.

Odpowiedź bramki dla taktowania 1kHz

https://youtu.be/bsh6cB6WpMw

Odpowiedź bramki dla taktowania 1MHz

https://youtu.be/WeT_lEvlh_0

Zerknijmy na programik testowy i sposób wywołania kolejnych funkcji SDK:

:arrow: https://github.com/bienata/AnalogDiscov ... _rom_1.lpr

Aby zdefiniować bramkę (czy inny układ kombinacyjny) należy określić jaki wyprowadzenia zajmujemy na jego wyjścia. Z wejściami jest prościej - idą sobie od DIO-0 w górę. Wyjścia wskazujemy wywołaniem funkcji FDwfDigitalOutEnableSet. Następnie konfigurujemy blok Digital IO do pracy jako ROM - to wywołanie FDwfDigitalOutTypeSet. Oczywiście taktowanie wyjściowego kanału określamy funkcyjką FDwfDigitalOutDividerSet, tryb pracy wyjścia - FDwfDigitalOutOutputSet. Tu uwaga: możliwe jest kilka wartości: open Drain, open Source, Three-state i Push-pull, które tu akurat wykorzystujemy.

dio_rom_1.lpr pisze:

Kod: Zaznacz cały

// robimy bramkę XOR
  // wejscia:
  //     A = DIO-0
  //     B = DIO-1
  // wyjsice:
  //     Y = DIO-15
 
  FDwfDigitalOutEnableSet( hAd2, DIO_0, false );
  FDwfDigitalOutEnableSet( hAd2, DIO_1, false );
  // DIO-15 - wyjscie bramki
  FDwfDigitalOutEnableSet( hAd2, DIO_15, true );
  //tryb pracy wyjscia - TS
  FDwfDigitalOutTypeSet( hAd2, DIO_15, DwfDigitalOutTypeROM );
  // CLK - 100MHz:
  FDwfDigitalOutDividerSet( hAd2, DIO_15, Cardinal(1) );
  FDwfDigitalOutOutputSet(hAd2, DIO_15, DwfDigitalOutOutputPushPull ); // push-pull


No i na koniec definicja bitowego wzorca - wywołanie funkcji FDwfDigitalOutDataSet czyli jak działa silnik. Wbijmy sobie zatem do głowy że - w trybie ROM wzorzec bitowy definiujemy dla każdego kanału (bitu wyjściowego) z osobna. Kolejne bity wzorca, jeśli by je ponumerowąć od zera idąc - odpowiadają kolejnym wartościom liczbowym na wejściach adresowych (stanom DIO-0..). Staje się jasne, że dla na przykład dwóch wejść i jednego wyjścia potrzebujemy sprecyzować 22 kombinacji zgodnie z równaniem wybranej bramki, czyli długość wzorca będzie 4 bity. To połowa bajtu, a takiego adres właśnie podajemy do generatora. Dla trzech bitów wejściowych - wzorzec będzie miał pełny bajt (23 bitów), i tak dalej. Zobaczmy wywołanie (truthTableXOR to zmienna typu byte):

dio_rom_1.lpr pisze:

Kod: Zaznacz cały

// DIO-1  DIO-0   DIO-15   nr.bitu w definicji
//  0      0        0      0
//  0      1        1      1
//  1      0        1      2
//  1      1        0      3
// kolejne bity:  76543210
truthTableXOR := %00000110;
FDwfDigitalOutDataSet( hAd2, DIO_15, @truthTableXOR, 8 );


Tu jest jeszcze w miarę, ponieważ definicja mieści się w jednym bajcie, ale dla więcej niż trzech wejść jako wzorzec będziemy podawali tablę bajtów, w której kolejne bity będą odpowiadały oczekiwanym odpowiedziom układu, taka bitowa koronka już nie jest intuicyjna.

Przerzutnik RS z bramek NAND

Wspominałam, że w trybie ROM możemy definiować zachowania tylko i wyłącznie układów kombinacyjnych, takich na liniowo połączonych bramkach. Ale kto nam zabroni z takich bramek zbudować sobie układ sekwencyjny, choćby najprostszy przerzutnik RS?

Zacznijmy od podstawowych składników - bramek NAND, tabele prawdy przygotowane w okienkach WaveForms widzimy na rysunku poniżej. Jak widać czarów tu nie ma żadnych, ale zauważmy - bloki danych dla NAND są definiowane osobno, to dla nas wygląda tak, jakby one były zupełnie rozłączne - co jest z resztą zgodne z oczekiwaniami.

11_rs_nand_truthtable.png


Jeżeli jednak zabierzemy się za przygotowanie tabeli z danymi dla funkcji FDwfDigitalOutDataSet to szybko dojdziemy do zawartości jak na poniższym rysunku:

10_rs_nandy.jpg


Widać od razu, że nasza definicja zawiera dwie logicznie rozłączne bramki NAND, ale korzystające ze wspólnej fizycznej definicji kolejnych stanów wejść. Ot, aplikacja WaveForms, chcąc zapewnić maksymalny komfort użytkownikowi te meandry adresacji ROM jakby zmiata pod dywan.
Przygotowanie wsadu dla własnego programiku wymaga jednak wniknięcia w takie detale, co właśnie widać.
Zauważamy także, że wzorzec bitowy odpowiedzi dla jednej bramki ma 16 bitów czyli 2 bajty, skutkuje to dwuelementową tabelą, taką podamy go generowania. Skoro mamy już bramki to spróbujmy z nich sklecić nasz przerzutnik RS, o proszę:

12_rs_sch.png


Fizyczna realizacja w formie plątaniny przewodów:

13_rs_IMG_4926.JPG


Oczywiście wstępny test czy to w ogóle ruszy przeprowadziłam na WaveForms, filmik poniżej:

https://youtu.be/AXe8ExplMhA

Skoro zadziałało, to powstał programik konfigurujący Digilentową puderniczkę: :arrow: https://github.com/bienata/AnalogDiscov ... _rom_2.lpr

No i wspominany szczegół do podawaniu wzorca - mamy teraz dwa bajty definicji:
dio_rom_2.lpr pisze:

Kod: Zaznacz cały

const romNAND_1 : array [0..1] of byte = ( $77, $77 );
FDwfDigitalOutDataSet( hAd2, DIO_15, @romNAND_1, 16 );


Pascalowy przerzutnik RS na żywo możemy podziwiać na filmiku:

https://youtu.be/U59VDCeabeU

A ja korzystając z okazji chcę wspomnieć o jednej, dotychczas pomijanej sprawie, o odczycie mówiąc wprost `na pałę` stanu cyfrowych wejść AD2. Przydatne to do monitorowania czy podglądu tego co aktualnie wyrabia nasze pudełko, ale należy pamiętać że dokonywane w taki sposób odczyty nie są z niczym synchronizowane, a odczyt następuje z zatrzasków wyjściowych dla linii ustawionych jako OUT i fizycznych wejść dla linii IN, jak w większości współczesnych mikrokontrolerów. Trzeba też pamiętać, ze SDK buforuje cześć informacji statusowych aby odciążyć komunikację z urządzeniem i taka przykładowo funkcja FDwfDigitalIOInputStatus odczyta dane z cache. Chcąc mieć nowe, świeże stany wejść należy przed tym wywołać funkcję FDwfDigitalIOStatus.

dio_rom_2.lpr pisze:

Kod: Zaznacz cały

repeat
  FDwfDigitalIOStatus( hAd2 );
  FDwfDigitalIOInputStatus(hAd2, @dwAllPins ); // DWORD
  dwAllPins := dwAllPins and %1100000000001111; // maska na nieuzywane piny
  writeln( binStr( dwAllPins, 16 )  );
  delay (100);
until false;


Fluorescencja retro - dekoder HEX

Nooo, oczywiście że będzie lampka VFD, śliczny zaiste okaz o symbolu IW-12 :arrow: https://static.elektroda.pl/attach/iw-12_1804.gif
Kolejne liczby binarne do dekodowania pozyskamy z polskiej produkcji licznika typu 7493, całość zabawki można przedstawić na schemacie jak poniżej:

21_7seg_sch.png


Fizyczna realizacja taka, przy okazji zauważamy alternatywne zastosowanie spinacza do prania i metalowej podstawki z lupką - można w tym trzymać sobie VFD lub Nixie podczas zdjęć.

22_7seg_vfd_7493.jpg


Tabela prawdy dekodera BIN/7SEG wygląda następująco i jest chyba zrozumiała.

23_7seg_truthtable.png


Dla wyjaśnienia dodam tylko, że wyjścia dekodera są zanegowane - ze schematu widać, że logiczne H zewrze segment do masy (wygasi), stan L - umożliwi świecenie, stąd negacja.

Plątanina nieco się rozrosła, więc test połączeń, a przede wszystkim przypisanie wyjść AD2 do segmentów lampy VFD sprawdziłam sobie na WaveForms, okienkiem Static IO, o tak:

https://youtu.be/hehVR33yY5Y

Trzeci programik, konfigurujący pudełko AD2 jako dekoder znajdziemy tu:
:arrow: https://github.com/bienata/AnalogDiscov ... _rom_3.lpr

Jest bliźniaczo podobny do tego od przerzutnika, ale ze względu na ilość wyjść - operacja konfigurowania wzorców jest w pętelce, takoż do obsługi w pętli została przygotowana definicja wzorców bitowych:

dio_rom_3.lpr pisze:

Kod: Zaznacz cały

type TROMData = array [0..1] of byte;
const romSegmentsData : array [0..6] of TROMData = (
     ( $12, $28 ),      // DIO-8
     ( $60, $d8 ),      // DIO-9
     ( $04, $d0 ),      // DIO-10
     ( $92, $84 ),      // DIO-11
     ( $ba, $02 ),      // DIO-12
     ( $8e, $20 ),      // DIO-13
     ( $83, $10 )       // DIO-14
);


dio_rom_3.lpr pisze:

Kod: Zaznacz cały

for i := 0 to 6 do
begin
   //...
   FDwfDigitalOutDataSet( hAd2, DIO_8 + i, @romSegmentsData[ i ], 16 );
end;


Działanie dekodera BIN/7SEG inicjowanego z Pascal przedstawia ostatni już dziś film:

https://youtu.be/i4ZlzJZ_YSM

Pamiątkowa fotka rupieciarni mej na koniec tych migających technikaliów:

99_7seg_bajzelek_IMG_4947.JPG


Ale po co?

Śródtytuł niezbyt wyszukany, ale pytanie o sens jak zawsze zasadne. Emulowanie prostych układów kombinacyjnych jakie umożliwia Analog Discovery 2 jest bardzo ciekawą i według mnie przydatną funkcjonalnością, szczególnie dla osób, które ciągle z elektroniką eksperymentują i ich dłubanina to jedno nieustające pasmo poszukiwań. Zauważmy, że decyzje projektowe typu - a wstawmy gdzieś ośmiowejściową bramką NAND mają dość mocne konsekwencje - poszukiwanie kostki 74LS30 lub budowę jej ekwiwalentu z układów o mniejszej liczbie wejść. Czas leci, nerwy słabsze jakby a przecież może się okazać, że to błędna droga i za chwilę z tego rozwiązania zrezygnujemy. I będziemy szukać bramki czterowejściowej jak 74LS20. Albo innej. Tu taka "udawaczka" fragmentu logiki jest moim zdaniem jak najbardziej zasadna - możemy zmieniać zdanie co chwila, wyklikując nowe rozwiązania na poczekaniu.
Inny przykład do opisywany wyżej dekoder - w kilka chwil możemy przerobić go na wersję "na prost", bez negacji - znika nam wtenczas dylemat czy pracujemy z wyświetlaczami wspólna anoda czy katoda - możemy się błyskiem dostosować. No i oczywiście skoro mamy pewną możliwość oddziaływania na czas propagacji takiej udawanej bramki (czy większej kombinatoryki) możemy wpiąć to do fizycznego układu i wykonać testy jaki wpływ ma czas odpowiedzi logiki na finalne działanie. Idę o zakład, że zjawiska typu hazard (układy kombinacyjne) będą łatwo obserwowalne. A skutki zjawiska wyścigu (układy sekwencyjne) było nawet widać na jednym z filmików, uważne oko złapie. Tyle w podsumowaniu - skoro funkcjonalność jest to trzeba ją rozpoznać i wycisnąć ostatnie bity. Prawie dosłownie.

#slowanawiatr
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
___________________________________________ ____ ___ __ _ _ _ _
J​eżeli dadzą ci papier w linie, pisz w poprzek. Juan Ramón Jiménez

Awatar użytkownika
gaweł
Expert
Expert
Posty: 665
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: [AD2][Pascal] Digital I/O - ROM Mode | przerzutnik RS i dekoder do rosyjskiej VFD | WaveForms SDK | cz.4

Postautor: gaweł » wtorek 08 sty 2019, 16:16

tasza pisze:Na egzaminie na prawo jazdy pytają blondynkę: proszę opowiedzieć jak działa silnik w samochodzie.
A mogę swoimi słowami? Może pani! Brum brum brum.


Na szczęście nie jesteś blondynką i potrafisz precyzyjnie i logicznie myśleć. Nie jest to kwestia "tak myślę", to jest kwestia "wiem o tym", zbyt długo Cię znam, może całą wieczność.

Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse


Wróć do „Inne języki programowania”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 4 gości