RABBIT 2000

Pozostałe układy mikrokontrolerów, układy peryferyjne i inne, nie mieszczące się w powyższych kategoriach.
Awatar użytkownika
gaweł
Geek
Geek
Posty: 1259
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

RABBIT 2000

Postautor: gaweł » poniedziałek 16 kwie 2018, 15:23

Dziwny jest ten świat

...zawracanie gitary, czyli relaks dla emocji...https://www.youtube.com/watch?v=Eh20YY-dFOQ

Ostatnio na tapecie mam tematy sieci ethernetowych w aplikacjach z mikrokontrolerami. No i przypomniałem sobie, że mam taki zestaw, co pozwala na zabawę w temacie. W sumie, to ten zestaw odleżał sobie tak trochę lat, by doczekać się swoich pięciu minut. Pierwszy kontakt (ponad 10 lat temu) był interesujący. Potem historia potoczyła się tak, że … zestaw powędrował gdzieś daleko … na półkę przywalony innymi szpargałami. Ostatnio wypłynął przy okazji jakiegoś sprzątania, więc trafił na mój stół.
rab01-ilu01.jpg
Zakupiłem go sobie kiedyś w ramach fascynacji procesorem Z80, no bo jak się przyjrzeć architekturze tego proca, to widać wyraźnie, że tworzą rodzinę (czyli mają wiele wspólnych genów). Proc został wyprodukowany przez Rabbit Semiconductor. Firma ta, jak podają różne ulotki, powstała w celu zaprojektowania lepszego mikroprocesora do użytku w rozwiązaniach o małych i średnich stopniach komplikacji. Pierwszym mikroprocesorem był Rabbit 2000, kolejny to Rabbit 3000 (w sumie było ich więcej). Rabbit Semiconductor ma wieloletnie doświadczenie w użyciu mikroprocesorów Z80, Z180 i HD64180 do budowy małych sterowników, procki Rabbit mają podobną architekturę i wysoki stopień zgodności z tymi mikroprocesorami.
W kwestii oprogramowania (bo w końcu każdy proc musi coś takiego mieć, inaczej jest tylko kawałkiem bezwartościowego złomu) Rabbit 3000 został zaprojektowany w ścisłej współpracy z Z-World, Inc. Firma ta stworzyła innowacyjny system programowania w języku C (Dynamic C). Z-World dostarcza oprogramowanie narzędziowe dla Rabbit 3000. W materiałach piszą, że pomimo że proc jest 8-bitowy, ma dużą szybkość obliczeń. Piszą również, że do eksperymentów nie są potrzebne emulatory. Rozumiem z tego, że proc posiada w sobie coś, co pozwala całemu światu na kontakt z jego wnętrzem. Dokonuje się tego za pomocą połączenia kabelkiem prostego interfejsu portu szeregowego w PC i systemu docelowego. Pozwala to na programowanie i debugowanie.
W pudełku, oprócz instalki oprogramowania narzędziowego oraz dokumentacji,
rab01-ilu02.jpg
jest plakat.
rab01-ilu03.jpg
Jest podana nazwa strony www, toteż wiedziony potrzebą poszerzenia wiedzy odpalam przeglądarkę internetową. I tu przydarzyła mi się przykra niespodzianka, taki kopniak w czułe miejsce (w końcu jestem sympatykiem zilogowych genów), takiej strony nie ma. Pierwsza myśl: królik zbankrutował? Wujek gugiel poproszony o wyjaśnienie sprawy, nieco rozwiał nadciągające czarne chmury. Jak twierdzi angielska wikipedia, „królicza korporacja” kolaborowała z Dynamic C (no to już wiemy) i 2006 roku została przejęta przez Digi International. Przed zakupem firma Rabbit Semiconductor była częścią Z-World, Inc. No cóż, pewne elementy rzeczywistości przechodzą z rąk do rąk. Widocznie nawet jakaś mała stabilizacja może prowadzić do marazmu, więc czasem musi coś zaiskrzyć by nie odejść w zapomnienie. Może tak było w przypadku królika, gdyż procki te są oferowane nawet dzisiaj (od przejęcia minęło 12 lat). Jakby przyjrzeć się temu co się aktualnie dzieje na świecie, to przejęcia są codziennością (choćby to, że Atmel stał się częścią Microchipa, czy Linear Technology występuje w barwach Analog Devices).
Odwiedzając stronę http://www.digi.com/products/rabbitprocessor
rab01-ilu04.png
widać, że procki Rabbit 2000 są nadal dostępne na rynku.
Posiadany zestaw badawczo-rozwojowy
rab01-ilu05.jpg
zawiera identyczny moduł, jaki jest oferowany przez Digi International.
Przyglądając się modułowi (góra)
rab01-ilu06.jpg
(dół)
rab01-ilu07.jpg
wytworzył mi się w głowie pewien konflikt logiczny. W dokumentacji od proca jest napisane, że to mikroprocesor. Na plakacie jest to przedstawione
rab01-ilu08.jpg
jakby to był mikrokontroler (zawierał w jednej strukturze jakieś peryferale). Kolejne zdziwienie, w króliczym chipie nie ma pamięci Flash ani pamięci RAM (są dodane w module jako komponenty zewnętrzne: 512 kB Flash i 512kB SRAM). Typowo mikrokontroler takie podzespoły integruje w jednej strukturze. Trochę to dziwne, ale … nie będę tego oceniał. Jest, jak jest, należy się do tego dostosować. To, że czegoś do końca nie rozumiem, nie znaczy, że tego nie ma (może kiedyś nadejdzie olśnienie i wszystko stanie się jasne).
Jak zajrzałem na stronę pl.farnell.com, to przeżyłem kolejny szok :shock: , tym razem cenowy. Jakby na to nie patrzeć, zabawa tymi modułami wymaga kupy kasy. No i druga sprawa: niektóre moduły są na wyprzedaży inne wycofane ze sprzedaży. Znaczy się, coś odchodzi do historii (bo w końcu nic nie jest wieczne) i należy poszukiwać nowych rozwiązań (a nie trwać przy swoich przyzwyczajeniach i wyobrażeniach).
Ale zanim ktoś zgasi światło w króliczym świecie, to … może warto zobaczyć jak wygląda ten świat, bo jak twierdzi angielska wikipedia, interesującą cechą króliczej rodziny jest środowisko programistyczne. Dynamic C, wyrosłe razem z prockami Rabbit, jest inne, zawiera swoje dodatki i niespójności w porównaniu ze standardem ANSI-C. Wręcz podąża swoimi własnymi ścieżkami.
Ponieważ standard ANSI-C nie uwzględnia specjalnych potrzeb systemów wbudowanych, konieczne jest odejście od normy w niektórych obszarach i tworzenie nowych w innych. Standard nie uwzględnia ważnych problemów systemów wbudowanych, takich jak pamięć tylko do odczytu i wbudowany język asemblera. Z tego powodu kompilatory przeznaczone dla systemów wbudowanych nie są w pełni zgodne z normą. Jako przykład dodatku, niech posłużą konstrukcje do wielozadaniowości. W Dynamic C są odpowiednie „zaklęcia” na tą okoliczność. Są to costate i slice. Jeszcze nie wiem do czego służą, ale mam nadzieję, że wszystko się wyjaśni. Jak mówią wojskowi: będzie rozpoznanie walką. To powiedzenie mające „militarny wydźwięk” ma zastosowanie w codzienności. Wszystko wymaga jakiegoś wysiłku, samo nie przychodzi. Aby zdobyć kolejny szczyt należy ruszyć swoje cztery litery, wyjść z domu i ruszyć na wycieczkę.
rab01-ilu09.jpg

Nad łóżkiem na ścianie wisi właściwe hasło motywacyjne: Nie narzekaj, że idziesz pod górę skoro zmierzasz na szczyt. No więc wycieczkę zaczynamy od zainstalowania Dynamic C. Instalacja jest typowa i nie zawiera żadnych niespodzianek. Na CD-ku znajdują się pliki z dokumentacją. Okazuje się, że w sieci są bardziej aktualne dane. Są to:
Rabbit 3000 Microprocessor Data Sheet - http://www.acierta-it.com/jas/v3.0/CD%2 ... 3000DS.pdf
Rabbit 3000 Microprocessor User’s Manual - http://datasheets.chipdb.org/Rabbit/3000/R3000UM.pdf
Rabbit 3000 Microprocessor Designer’s Handbook - http://datasheets.chipdb.org/Rabbit/3000/R3000DH.pdf
RabbitCore RCM3400 C-Programmable Analog Core Module with 10/100Base-T Reference Design User’s Manual - http://ftp1.digi.com/support/documentat ... 0122_P.pdf
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » wtorek 17 kwie 2018, 22:16

Pierwszy program
rab02_ilu00.jpg

gitarowa nuta
https://www.youtube.com/watch?v=iHS3_q7dlxk


Pierwszy program, pierwsza niedaleka wycieczka w świat Z-WORLD (czy Z WORLD można przetłumaczyć na zaskakujący świat? :) ). Po odpaleniu programu należy utworzyć projekt, opcja File → Project → Create (żadna filozofia).
rab02-ilu01.png
Potem utworzyć plik z programem (File → New). Po wklepaniu tekstu programu plik należy zapisać na dysku (File → Save As). W sumie nic nowego pod słońcem.

Kod: Zaznacz cały

/**********************
Pierwszy projekt dla Rabbit 2000 (Dynamic C)
**********************/

main ( )
{
  unsigned int i , j ;
  //---------------------------------
  i = 0 ;
  for ( ; ; )
  {
    i++ ;
    printf ( "I = %d\n" , i ) ;
    for ( j = 0 ; j < 50000 ; j ++ )
      ;
  } /* for */ ;
} /* main */
Program jest tak prosty, że nawet nie ma gdzie się pomylić.
rab02-ilu02.png
Chciałem jedynie uruchomić kompilację. No więc klik na Compile.
rab02-ilu03.png
I tu pierwsza niespodzianka (ten świat jest dziwny).
rab02-ilu04.png
Nie chce się skompilować, bo … nie widzi króliczego proca. Nie widzi?, niech okulary założy. Pierwszy raz coś mi się takiego przytrafiło, kompilator potrzebuje procka, by skompilować program. Nie rozumiem, ale akceptuję. Podłączam znajdujący się w zestawie kabelek do portu COM w kompie i odpowiednim złączu w zestawie badawczym. Ponowna kompilacja.
rab02-ilu05.png
Kompiler informuje mnie, że kompiluje do pamięci Flash oraz
rab02-ilu06.png
ładuje program do pamięci Flash. Zapewne tej w module, bo sam proc nie ma żadnej pamięci na program. Tu generuje się kilka pytań:
  • przecież do proca może być przypięta pamięć flash o różnej pojemności, skąd Z World wie, jaka jest aktualnie użyta, są przecież różne algorytmu programowania,
  • jak jest programowana ta pamięć, skoro interfejs jest szeregowy i jak widać po kabelku, nie ma zbyt dużo sygnałów do użycia.
Może
  • skoro flash jest w przestrzeni proca (szyna danych proca i szyna adresowa proca) a te nie są wyprowadzone na złącza króliczego modułu, to znaczy, że proc wachluje tymi liniami a to prowadzi do wniosku, że musi być w tym procu jakiś kawałek loadera.
Poza tym, trochę to dziwne, chciałem tylko skompilować, bez ładowania do pamięci. Czy to takie dziwne? Chciałem tylko skompilować a dostałem coś extra niejako w promocji. Skoro program znalazł się w pamięci Flash, to może coś da się podziałać dalej. Klik na Run.
rab02-ilu07.png
Zmieniła się ikonka z Run na Stop, a bieżące okienko przełączyło się na wyświetlanie strumienia stdio.
rab02-ilu08.png
Znaczy, że standardowy strumień wyjściowy programu przełączył się na serial, który jest odbierany i wyświetlany przez środowisko Dynamic C. Jest to z pewnością fajna sprawa, ale czy to oznacza „utratę” jednego UARTU na rzecz stdio (temat do głębszych badań: czy można odpiąć stdio od UART'a, bo może zaistnieć taka potrzeba oraz, czy da się emulować w ten sposób strumień wejściowy, to pozwoli „mieć” klawiaturę w procu przynajmniej w fazie eksperymentów może być przydatne). No to klik na Stop. Program się zatrzymał (znaczy przestał wysyłać coś do strumienia stdio) i przełączył się na okienko w tekstem programu. Ponownie klik na Run. Okazuje się, że program idzie dalej, nie zaczyna od początku.
rab02-ilu09.png
Stop nie znaczy stop? Znaczy się, że źle zrozumiałem? Spodziewałem się, że nastąpi zatrzymanie (programu) a nastąpiła pauza (w programie). Drobna różnica interpretacyjna i w sumie jest to kwestia punktu widzenia. Można to i tak widzieć, zdarza się, że jakieś słowo ma kilka znaczeń.
W takim razie jak uruchomić program od początku? Jest w opcjach Run,
rab02-ilu10.png
ale opcja Reset Pogram jest dostępna tylko w sytuacji, gdy program jest zatrzymany (po Stop). Ponowne uruchomienie programu i … program zaczyna od początku.
Jeszcze jeden eksperyment. Na płycie króliczego zestawu jest przycisk Reset. No więc … do odważnych świat należy.
rab02-ilu11.png
No tak... chyba nie o to chodziło.
Zerwało się połączenie debugera. Po kliknięciu na OK, ponownie klik na Run. Program został ponownie załadowany do pamięci i uruchomiony. W okienku stdio są zapisy. No cóż, taka filozofia, pozostaje się dostosować.
W opcjach znajduję Inspect (zwyczajowo do podglądania stanu zmiennych) i dalej na Add Watch.
rab02-ilu12.png
Wpisuję nazwę zmiennej.
rab02-ilu13.PNG
Implikuje to wyświetlenie
rab02-ilu14.PNG
stanu zmiennej w odpowiednim okienku.
Po każdym zatrzymaniu programu (znaczy w moim rozumieniu: pauzie), odświeżane są informacje w okienku Watches – to miłe.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » środa 18 kwie 2018, 12:07

Drugie starcie

Sukces pierwszej wycieczki... rośnie apetyt na więcej. Skoro jest dostępny strumień wyjściowy, to czy daje się prosto użyć strumienia wejściowego w stdio. Utworzony zostaje drugi projekt, z wklepaniem prostego programiku.

Kod: Zaznacz cały

/**********************
Drugi projekt dla Rabbit 2000 (Dynamic C)
**********************/

main ( )
{
  char Ch ;
  //---------------------------------
  for ( ; ; )
  {
    printf ( "\n* * * przed kbhit * * *\n" ) ;
    while ( ! kbhit ( ) )
      ;
    Ch = getchar ( ) ;
    printf ( "\n* * * po kbhit, kod znaku %d * * *\n" , Ch ) ;
  } /* for */ ;
} /* main */
Program jest prosty, że nie powinno być pomyłki. Kompilacja (połączona z ładowaniem kodu do pamięci Flash) i nadchodzi chwila prawdy. Działa.
rab03-ilu01.png
Na klawiaturze peceta naciskam spację (kod znaku 32), klawisz 'a' (małą → kod znaku 97), potem 'A' (wielką → kod znaku 65), potem jakieś inne znaki. Odwzorowane w króliczym wejściowym strumieniu stdio są znaki pisarskie. Próba kombinacji generującej znaki kontrolne nie powodzi się. Wyfiltrowuje je Dynamic C, bo przykładowo na Ctrl-O chce otworzyć plik (File → Open), ale Enter działa. Dobre i to. Takie funkcjonalności stają się inspirujące do kolejnych eksperymentów na przyszłość.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » środa 18 kwie 2018, 14:28

Zaskoczony :shock:
El Condor Pasa – wolność i harmonia w przestrzenihttps://www.youtube.com/watch?v=uzBS-dx_wNw
Znalazłem taki przykładowy program z króliczego świata, program do generowania liczb losowych. Zawsze mnie zastanawiało, jak bardzo losowe są liczby losowe? Jakoś trudno mi uwierzyć w prawdziwą losowość, w końcu to obrabia jakiś algorytm, który zawsze wyrachuje identycznie (no chyba, że proc się popsuje i przestanie właściwie realizować operacje arytmetyczne). Z reguły generatory liczb losowych są inicjowane losową liczbą, ale ją też trzeba jakoś … zdobyć. Jeżeli w układzie jest jakiś czynnik ludzki, to może są jakieś szanse. Ot choćby stan inkrementowanego licznika do pierwszego naciśnięcia jakiegoś przycisku. Jednak, jeżeli proc startuje od reseta, zawsze w identycznym środowisku, to… jakoś mi się nie widzi. Znaczy, że w takim układzie losowość jest zdeterminowana? Niby należy spodziewać się nieznanego, a tu wychodzi, że tak miało być, w końcu to algorytm.

Kod: Zaznacz cały

#class auto

// All Dynamic C versions since 8.01 have included the MD5.LIB library, so
//  we can define RAND_USE_MD5 even though we don't demonstrate RAND.LIB's
//  seed_hash() functionality in this sample program.
#define RAND_USE_MD5

// uncomment the following line to make RAND.LIB functions debuggable
//#define RAND_DEBUG

#use "rand.lib"

void main ()
{
   auto char *salt;
   auto unsigned matchValue, testValue;
   auto unsigned long count;

   // initialize the count value to zero for the following comparison
   //  as well as for entry into the while loop later on . . .
   count = 0ul;

   if (memcmp(&SysIDBlock.macAddr[2], &count, sizeof(count))) {
      // if the System ID block contains an actual (non-zero) MAC address,
      //  then use it as our pseudo-random seed "salt" value
      salt = &SysIDBlock.macAddr[2];
   } else {
      // otherwise, don't bother with a psuedo-random seed "salt" value at all
      salt = NULL;
   }
   // NB: An application which requires a secure pseudo random number generator
   //     wouldn't (shouldn't!) call seed_init with anything other than a NULL
   //     "salt" parameter.
   seed_init(salt);

   while (1) {

      // get the pseudo-random integer sequence's next value from our range of
      //  [2000, 2999] inclusive
      testValue = rand16_range(2000u, 1000u);

      // catch and report any (impossible) errors here
      if (2000u > testValue || 2999u < testValue) {
         printf("\n\nError, %u is not in the range [2000, 2999] inclusive!\n\n",
                testValue);
         exception(-ERR_RANGE);
         exit(-ERR_RANGE);
      }

      // display test and / or match values information
      if (count) {
         if (matchValue == testValue) {
            // found a match!
            printf("\n%8u  (Match after %lu pseudo-random sequence values.)\n",
                   testValue, count);
            printf("Press a key to continue.\n");
            while(!kbhit());   // wait for the User to press a key
            getchar();   // throw the keypress away and continue on . . .
            count = 0ul;   // reset the count for the next match test
         } else {
            // no match, just display the test value
            printf("%8u", testValue);
            ++count;
         }
      } else {
         // count is zero so select a new match value to search for
         matchValue = testValue;
         printf("\n%8u  (Searching for the next occurrence of %u.)\n",
                testValue, matchValue);
         ++count;
      }
   }
}
No więc przystępuję do kompilacji, a tu … niespodzianka.
rab04-ilu01.png
Myszka mi się omsknęła i wybrałem inną opcję: Compile → Compile to .bin File → Compile to Flash.
W dziwnym świecie, uruchomiła się kompilacja, która jak sugeruje tytuł okienka, nie wymaga systemu docelowego.
rab04-ilu02.png
Mało tego, nawet się poprawnie skompilowało.
rab04-ilu04.png
No to spróbowałem z odłączonym zestawem. Wyszło identycznie. Prosty wniosek, nie zawsze potrzebny jest układ docelowy. No cóż, należy uderzyć się w pierś i przyznać, że... chyba trochę naurągałem króliczemu światu i należą się jakieś przeprosiny. Więc przepraszam króliczy świat :) . Można to rozpatrywać w kategoriach losowości i prawdopodobieństwa. Eksperymentując z algorytmem generującym liczby losowe, zaistniało zjawisko losowe. Co za ironia. A może tak miało być i było to zdeterminowane? Tak gwoli ścisłości, wracając do króliczego świata, to nie czuję się bym w czymś zawinił. Ot, bazując na obserwacji został wyciągnięty jakiś wniosek, który później okazał się błędny. Tak bywa, jeżeli wiedzę zdobywa się w kategoriach wojskowych: rozpoznanie walką. No niby można było zajrzeć do dokumentacji, ale... nie istotne. Jest jak jest. Jeszcze czeka wiele potyczek, bo każdy manual nie zawiera odpowiedzi na wszystkie możliwe pytania i trzeba samemu się natrudzić by poznać wszystkie odpowiedzi. Po załadowaniu programu do systemu docelowego, wyszło
rab04-ilu05.PNG
Czy są to liczby losowe? Może tak, może nie, kwestia punku widzenia.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » środa 18 kwie 2018, 20:29

Wielozadaniowe starcie
Wielozadaniowa nutahttps://www.youtube.com/watch?v=YbF_yB57IwI
W Dynamic C zostało wprowadzonych kilka rozwiązań spoza normy ANSI C mające zastosowanie dla wielozadaniowości. Wielozadaniowość, to tak jakby w króliczym procku zostało uruchomionych kilka programów, które międlą się równolegle. Ogólnie wiadomo, że jest to jakaś iluzja, bo klasyczne procki są sekwencyjne (realizują instrukcje programu sekwencyjnie). W rzeczywistości wielozadaniowość jest realizowana w ten sposób, że czas procesora jest cyklicznie przydzielany kolejnym potokom programu. W środowisku wielozadaniowym występuje więcej niż jedno zadanie (każde reprezentujące swoją sekwencję operacji), które mogą wydawać się, że są wykonywane równolegle. W rzeczywistości pojedynczy procesor w danej chwili może wykonywać tylko jedną instrukcję. Każde zadanie może wykonać część swojej pracy, podczas gdy inne zadania (potoki) czekają na jakieś zdarzenie lub na coś do zrobienia. Jeżeli przełączanie następuje szybko, to uzyskuje się pozór wykonywania równoległego iluś zadań.
W przypadku braku wielozadaniowego systemu operacyjnego, programista, który rozwiązuje problem jako wielozadaniowy, często wymyśla rozwiązanie, które można opisać jako maszyny stanu przełączane z dużą prędkością. Oznacza to, że program składa się z dużej, nieskończonej pętli. Wewnątrz tej pętli zadania są wykonywane przez małe fragmenty programu, które przechodzi przez serię stanów. Maszyny stanów mogą stać się dość skomplikowane, obejmujące dużą liczbę zmiennych stanu i dużą liczbę stanów. Zaletą automatu stanów jest to, że unika on ciągłego oczekiwania, które czeka w pętli, dopóki warunek nie zostanie spełniony. W ten sposób jedna wielka pętla może obsługiwać dużą liczbę maszyn stanów, z których każda wykonuje swoje własne zadanie, a nikt nie jest zajęty czekaniem. Współpracujące wielozadaniowe rozszerzenia językowe dodane do Dynamic C używają wielkiej pętli i koncepcji maszyny stanów. Stan zadania jest pamiętany przez wskaźnik instrukcji, który zapisuje miejsce, w którym wykonanie bloku instrukcji zostało wstrzymane w oczekiwaniu na zdarzenie.
W Dynamic C występuje rozszerzenie językowe wspierające prostą wielozadaniowość. Do tego służy zaklęcie costate. Postać zapisu jest następująca:
costate [ name [state] ] { [ statement ; | yield ; | abort ; | waitfor ( expression ) ; ] . . .}
gdzie :
  • costate jest słowem kluczowym,
  • name (jest opcjonalne) i oznacza nazwę ciągu costate, brak nazwy oznacza, że costate jest nienazwane,
  • state (jest opcjonalne) – stan może być jednym z następujących: always_on lub init_on (znaczenie tego z dokumentacji jest trochę niejasne, więc trzeba będzie rozpoznać to walką), nienazwane ciągi costatealways_on,
  • statement – to ciąg instrukcji języka,
  • yield – dodane w Dynamic C słowo kluczowe, którego zadaniem jest przełączenie na kolejne costate,
  • abort – dodane w Dynamic C słowo kluczowe, którego zadaniem jest zaniechanie realizacji ciągu costate,
  • waitfor ( expression ) – dodane w Dynamic C słowo kluczowe (to nie jest wywołanie funkcji), którego zadaniem jest zawieszenie danego costate do chwili zajścia warunku określonego przez expression.
No, to jak wygląda to w praniu. Powstaje program:

Kod: Zaznacz cały

main ( )
{
  int i ;
  //---------------------------------------------------------------
  for ( ; ; )
  {
    costate
    {
      for ( i = 0 ; i < 30000 ; i++ )
      {
        yield ;
      }
    }
    costate
    {
      waitfor ( DelayMs ( 500 ) ) ;
      printf ( "i = %d\n" , i ) ;
    }
  }
}
Kompilacja programu (połączona z załadowaniem go do pamięci flash). Po uruchomieniu programu jego strumień wyjściowy stdio wygląda następująco:

Kod: Zaznacz cały

i = 14011                                                                       
i = 28013                                                                       
i = 12032                                                                       
i = 26051                                                                       
i = 10066                                                                       
i = 24063                                                                       
i = 8081                                                                       
i = 22104                                                                       
i = 6121                                                                       
i = 20143                                                                       
i = 4163                                                                       
i = 18162                                                                       
i = 2178                                                                       
i = 16199                                                                       
i = 217                                                                         
i = 14243                                                                       
i = 28265                                                                       
i = 12285                                                                       
i = 26278                                                                       
i = 10298                                                                       
i = 24319                                                                       
i = 8337                                                                       
i = 22362                                                                       
i = 6382                                                                       
i = 20380                                                                       
i = 4395                                                                       
i = 18417
W programie są dwa zadania: jedno inkrementuje ciągle liczbę, drugie co pól sekundy „drukuje” tą liczbę do strumienia stdio. W wynikach widać jakiś asynchronizm, zdarzenie upłynięcia czasu w jednym ciągu costate, „trafia” drugi ciąg costate w różnych stanach.
Drobna modyfikacja programu (usuwamy zaklęcia yield).

Kod: Zaznacz cały

main ( )
{
  int i ;
  //---------------------------------------------------------------
  for ( ; ; )
  {
    costate
    {
      for ( i = 0 ; i < 30000 ; i++ )
        ;
    }
    costate
    {
      waitfor ( DelayMs ( 500 ) ) ;
      printf ( "i = %d\n" , i ) ;
    }
  }
}
Tym razem wynik jest następujący:

Kod: Zaznacz cały

i = 30000                                                                       
i = 30000                                                                       
i = 30000                                                                       
i = 30000                                                                       
i = 30000                                                                       
i = 30000                                                                       
i = 30000                                                                       
i = 30000                                                                       
i = 30000
Wychodzi, że yield (jak jest) za każdym obrotem pętli przełącza zadanie na inne (wtedy wychodzi asynchronizm wydruków). Jeżeli jest brak yield, to pętla wykonuje się do końca i dopiero wtedy przełącza się na inne zadanie.
No to jeszcze inny eksperyment:

Kod: Zaznacz cały

#define LEDON   1
#define LEDOFF   0

int ledstatus;

leds_setup ( )
{
   ledstatus = PDDRShadow | 0xC0 ;
   WrPortI( PDDR , & PDDRShadow , ledstatus ) ;
}


LED1 ( int what )
{
   if ( what == LEDON )
      ledstatus &= 0xBF ;
   else
      ledstatus |= 0x40 ;
   WrPortI ( PDDR , NULL , ledstatus ) ;
}


LED2 ( int what )
{
   if ( what == LEDON )
      ledstatus &= 0x7F ;
   else
      ledstatus |= 0x80 ;
   WrPortI ( PDDR , NULL , ledstatus ) ;
}


main ( )
{
  //---------------------------------------------------------------
  brdInit ( ) ;
  leds_setup ( ) ;
  for ( ; ; )
  {
    costate
    {
      waitfor ( DelayMs ( 500 ) ) ;
      LED1 ( LEDON ) ;
      yield ;
      waitfor ( DelayMs ( 500 ) ) ;
      LED1 ( LEDOFF ) ;
      yield ;
    }
    costate
    {
      waitfor ( DelayMs ( 300 ) ) ;
      LED2 ( LEDON ) ;
      yield ;
      waitfor ( DelayMs ( 300 ) ) ;
      LED2 ( LEDOFF ) ;
      yield ;
    }
  }
}
Po uruchomieniu programu w króliczym zestawie, oba LED'y mrugają każdy swoim, innym rytmem. Mam wrażenie, że zaczynam rozumieć filozofię costate.
rab05-ilu01.jpg
Tak trochę w technologii „rzutu na taśmę”, postanowiłem usunąć z programy wszystkie instrukcje yield, zobaczymy co z tego wychodzi. Istotna część wygląda następująco:

Kod: Zaznacz cały

main ( )
{
  //---------------------------------------------------------------
  brdInit ( ) ;
  leds_setup ( ) ;
  for ( ; ; )
  {
    costate
    {
      waitfor ( DelayMs ( 500 ) ) ;
      LED1 ( LEDON ) ;
      waitfor ( DelayMs ( 500 ) ) ;
      LED1 ( LEDOFF ) ;
    }
    costate
    {
      waitfor ( DelayMs ( 300 ) ) ;
      LED2 ( LEDON ) ;
      waitfor ( DelayMs ( 300 ) ) ;
      LED2 ( LEDOFF ) ;
    }
  }
}
Po uruchomieniu, całość zachowuje się identycznie. Może zaklęcie waitfor zawiera w sobie już yield? Miałoby to sens.
Reasumując na zakończenie, funkcjonalnie trochę przypomina to filozofię z MODULA 2, z tym, że tam jako task występuje wskazana procedura, a tutaj jest to jakiś fragment ujęty w nawiasy { } poprzedzony zaklęciem costate.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » czwartek 19 kwie 2018, 22:14

Ostatni program, ten do mrugania diodami LED, rzeczywiście znajduje się w pamięci nieulotnej.
rab06-ilu01.jpg
Device przeleżało przez noc bez prądu i obecnie jedynie z przyłączonym kabelkiem od zasilania wstało samodzielnie na nogi. Właściwie nic w tym dziwnego, można się tego spodziewać, ale o wszystkim się trzeba przekonać samemu.
Króciutki filmik:
rabbit6.mov
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » piątek 20 kwie 2018, 02:42

Szersze wody
rab07-ilu00.jpg

Nie ma to jak harmonia.https://www.youtube.com/watch?v=3J0_mnFsdso
Dreptanie po najbliższej okolicy staje się mało ciekawe. Nadeszła pora sięgnąć po więcej. Te więcej, to już całkiem spory teren, obejmuje swym zasięgiem 3 kondygnacje, w końcu kabelek eternetowy rozchodzi się po całej chałupie. Z punktu widzenia sieci istotne elementy środowiska pokazuje następujący rysunek:
rab07_ilu01.png
Korzystając z maleńkiego króliczego multitaskingu, powstaje niby prosty program. Prosty, bo nic skomplikowanego nie robi, jednak, gdy zajrzeć pod maskę, to widać ogrom wykonanej programowej pracy. Taki niepozorny ping w rzeczywistości to ogrom działań, których nie widać. Zagłębiając się w szczegóły dopiero można dostrzec złożoność zagadnienia, jednak nie każdy ma ochotę poznać prawdziwe oblicze tego świata. Przechodzenie informacji przez poszczególne warstwy modelu OSI, zrozumienie mechanizmów komunikacji, itp. to całkiem spore wyzwanie. Ten cały ogrom działań jest rzeczywisty, istnieje. By go dostrzec wystarczy zmienić swój własny fokus, wyrazić chęć a pomocna dłoń z pewnością się znajdzie.
Mając pewne doświadczenia w czarowaniu w króliczej przestrzeni, tworzę nowy program. Rzecz jasna musi zachodzić synergia i konsensus pomiędzy poszczególnymi elementami. Naukę komunikacji należy zacząć od podstawowego poziomu i dogadać się z biblioteką procedur. W świecie Z (Z WORLD) całość jest podana źródłowo, więc można go adaptować do własnych potrzeb i na tej bazie wyprodukować swój własny maleńki świat. Ktoś już zadbał i stworzył ileś wariantów, nam zostało wybrać jeden, ten właściwy.
W pliku TCP_CONFIG.LIB (plik jest w rzeczywistości zapisem źródłowym) jest zawarte kreowanie rzeczywistości na podstawie wymagań programisty. Nadając stałej o nazwie TCPCONFIG odpowiednią wartość można uzyskać różne rozwiązania. Przykładowo dla:
  • TCPCONFIG = 1 – mamy typową sieć ethernetową o ustalonych parametrach (własny adres IP, maska podsieci, adres IP bramy domyślnej, adres serwera DNS),
  • TCPCONFIG = 2 – mamy sieć PPP bazującą na porcie szeregowym C,
  • TCPCONFIG = 3 – mamy sieć sieć ethernetową konfigurowaną automatycznie (DHCP).
Dostosowałem jedynie wstępną propozycję do własnych potrzeb. W końcu każdy jest przecież indywidualnością (istotny fragment TCP_CONFIG.LIB):

Kod: Zaznacz cały

//   #define _PRIMARY_STATIC_IP      "10.10.6.100"
//   #define _PRIMARY_NETMASK      "255.255.255.0"
//   #ifndef MY_NAMESERVER
//      #define MY_NAMESERVER      "10.10.6.1"
//   #endif
//   #ifndef MY_GATEWAY
//      #define MY_GATEWAY         "10.10.6.1"
//   #endif
   #define _PRIMARY_STATIC_IP      "192.168.0.44"
   #define _PRIMARY_NETMASK      "255.255.255.0"
   #ifndef MY_NAMESERVER
      #define MY_NAMESERVER      "192.168.0.254"
   #endif
   #ifndef MY_GATEWAY
      #define MY_GATEWAY      "192.168.0.254"
   #endif
Przy takim rozwiązaniu we własnym programie wystarczy zdefiniować stałą w następujący sposób:

Kod: Zaznacz cały

#define TCPCONFIG  1
i w króliczym środowisku jest sieć o wymaganych cechach.
Program do eksperymentów jest następujący:

Kod: Zaznacz cały

#define PORTA_AUX_IO
#class auto

#define TCPCONFIG 1
#define PING_WHO         "51.255.157.203"
//"192.168.0.67"

#define PING_DELAY      2000

#memmap xmem
#use "dcrtcp.lib"

#define LEDON   1
#define LEDOFF   0

int ledstatus ;

leds_setup ( )
{
   ledstatus = PDDRShadow | 0xC0 ;
   WrPortI ( PDDR , & PDDRShadow , ledstatus ) ;
} /* leds_setup */


pingoutled ( int NewState )
{
  if ( NewState == LEDON )
    ledstatus &= 0xBF ;
  else
    ledstatus |= 0x40 ;
  WrPortI ( PDDR , NULL , ledstatus ) ;
} /* pingoutled */


pinginled ( int NewState )
{
  if ( NewState == LEDON )
    ledstatus &= 0x7F ;
  else
    ledstatus |= 0x80 ;
  WrPortI ( PDDR , NULL , ledstatus ) ;
} /* pinginled */


main ( )
{
  longword seq ;
  longword ping_who ;
  longword tmp_seq ;
  longword time_out ;
  word Valid ;
  word NewHostData ;
  word Loop ;
  char Ch ;
  char * PCh ;
  char HostIP [ 40 ] ;
  char TmpHostIP [ 40 ] ;
  char buffer [ 100 ] ;
  //-----------------------------------------------------------------
  brdInit ( ) ;
  seq = 0 ;
  leds_setup ( ) ;
  sock_init ( ) ;
  printf( "Moj adres IP = %s\n" ,
          inet_ntoa ( buffer , gethostid ( ) ) ) ;
  printf( "Adres IP DNS = %s\n" , MY_NAMESERVER ) ;
  printf( "Adres IP GW = %s\n" , MY_GATEWAY ) ;
  printf( "\n\n" ) ;
  strcpy ( HostIP , PING_WHO ) ;
  NewHostData = 1 ;
  Valid = 0 ;
  for ( ; ; )
  {
    if ( NewHostData )
    {
      NewHostData = 0 ;
      ping_who = resolve ( HostIP ) ;
      if ( ping_who == 0 )
      {
        Valid = 0 ;
        printf ( "Blad: cos krzywo jest wklepane: %s\n" , HostIP ) ;
      } /* if ... */
      else
      {
        Valid = 1 ;
        printf ( "\nPingowanie hosta IP=%s\n\n" , HostIP ) ;
      } /* if ... else */ ;
    } /* if */ ;
    tcp_tick ( NULL ) ;
    costate
    {
      if ( Valid )
      {
        waitfor ( DelayMs ( PING_DELAY ) ) ;
        printf ( "Ping wyslany do %s\n" , HostIP ) ;
        _ping ( ping_who , seq++ ) ;
        pingoutled ( LEDON ) ;
        waitfor ( DelayMs ( 50 ) ) ;
        pingoutled ( LEDOFF ) ;
      } /* if */ ;
    } /* costate */
    costate
    {
      if ( Valid )
      {
        time_out = _chk_ping ( ping_who , & tmp_seq ) ;
        if ( time_out != 0xffffffff )
        {
          printf ( "Odebrano odpowiedz na ping: %ld\n" , tmp_seq ) ;
          pinginled ( LEDON ) ;
          waitfor ( DelayMs ( 50 ) ) ;
          pinginled ( LEDOFF ) ;
        } /* if */
      } /* if */ ;
    } /* costate */ ;
    costate
    {
      if ( kbhit ( ) )
      {
        for ( Loop = 0 ; Loop < 40 ; Loop ++ )
          TmpHostIP [ Loop ] = 0 ;
        PCh = TmpHostIP ;
        Ch = getchar ( ) ;
        * PCh ++ = Ch ;
        for ( ; ; )
        {
          if ( ! kbhit ( ) )
            yield ;
          else
          {
            Ch = getchar ( ) ;
            if ( Ch < 0x20 )
            {
              * PCh = 0 ;
              NewHostData = 1 ;
              printf ( "\n\nNowy host: %s\n\n" , TmpHostIP ) ;
              strcpy ( HostIP , TmpHostIP ) ;
              break ;
            } /* if ... */
            else
            {
              * PCh ++ = Ch ;
              printf ( "\nMasz wklepane: %s\n" , TmpHostIP ) ;
            } /* if ... else */ ;
          } /* if ... else */ ;
        } /* for */ ;
      } /* if */ ;
    } /* costate */ ;
  } /* for */ ;
} /* main */
W programie są trzy taski:
  • do wysyłania ping,
  • do odbierania ping,
  • do wklepania nowego adresu IP do pingowania (wykorzystując króliczy wejściowy strumień stdio), który wstępnie jest określony na przykładowy adres IP=51.255.157.203 (adres IP wskazujący na elportal.pl), można go poznać wysyłając sygnał ping z kompa:
    rab07_ilu02.png
Uruchomiony program wygenerował następujące wyniki:
Moj adres IP = 192.168.0.44
Adres IP DNS = 192.168.0.254
Adres IP GW = 192.168.0.254

Pingowanie hosta IP=51.255.157.203

Ping wyslany do 51.255.157.203
Odebrano odpowiedz na ping: 0
Ping wyslany do 51.255.157.203
Odebrano odpowiedz na ping: 1
(...)

Masz wklepane: 19
Masz wklepane: 192
Masz wklepane: 192.
Masz wklepane: 192.1
Masz wklepane: 192.16
Masz wklepane: 192.168
Ping wyslany do 51.255.157.203
Odebrano odpowiedz na ping: 11

Masz wklepane: 192.168.
Masz wklepane: 192.168.0
Masz wklepane: 192.168.0.
Ping wyslany do 51.255.157.203
Odebrano odpowiedz na ping: 12

Masz wklepane: 192.168.0.6
Masz wklepane: 192.168.0.67

Nowy host: 192.168.0.67


Pingowanie hosta IP=192.168.0.67

Ping wyslany do 192.168.0.67
Odebrano odpowiedz na ping: 13
(...)

Masz wklepane: 19
Masz wklepane: 192
Masz wklepane: 192.
Masz wklepane: 192.1
Masz wklepane: 192.16
Ping wyslany do 192.168.0.67
Odebrano odpowiedz na ping: 22

Masz wklepane: 192.168
Masz wklepane: 192.168.
Masz wklepane: 192.168.0
Masz wklepane: 192.168.0.
Masz wklepane: 192.168.0.2
Masz wklepane: 192.168.0.25
Ping wyslany do 192.168.0.67
Odebrano odpowiedz na ping: 23

Masz wklepane: 192.168.0.254

Nowy host: 192.168.0.254


Pingowanie hosta IP=192.168.0.254

Ping wyslany do 192.168.0.254
Odebrano odpowiedz na ping: 24
Ping wyslany do 192.168.0.254
Odebrano odpowiedz na ping: 25

Ze swego kompa (192.168.0.67) daje się sięgnąć do świata królika (PING 192.168.0.44):
rab07_ilu03.png

No zaczyna robić się coraz ciekawiej :)
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » piątek 20 kwie 2018, 22:30

Mówimy jedno, myślimy o innym
Pianino ma coś ze szlachetności...https://www.youtube.com/watch?v=Z4xSbNAMKIA
Sieć internet, ta kojarzona ze stronami www (by nie było niejednoznaczności interpretacyjnej), to jedno z zastosowań całej gamy możliwych użyć sieci ethernetowej. By sięgnąć po zawartość strony, należy nawiązać połączenie TCP na ściśle określony numer portu. Takie, dobrze skierowane „poproszę”. W odpowiedzi (na to poproszę) przyjdzie samo. O cokolwiek poprosimy, aby tylko dobrze skierować pytanie, przyjdzie. Niestety wymaga to pewnych zabiegów, bo jak chcemy coś od microgeek.eu, to należy zapytać eeee.... no właśnie, kogo?
Do eksperymentu powstaje odpowiedni program:

Kod: Zaznacz cały

#define PORTA_AUX_IO
#class auto
 /***************************************************
 * moj adres IP jest  192.168.0.44                  *
 * maska podsieci jest 255.255.255.0                *
 * brama domyslna jest 192.168.0.254                *
 * serwer DNS jest 192.168.0.254                    *
 ****************************************************/
#define TCPCONFIG 1

#use dcrtcp.lib

void DNSResolve ( char * HostName )
{
  longword HostIP ;
  char Buffer [ 20 ] ;
  //---------------------------------------------------------------------------
     HostIP = resolve ( HostName ) ;
     if ( HostIP == 0 )
      printf ( "\nNie mozna znalezc adresu IP dla domeny %s\n" , HostName ) ;
    else
   {
     inet_ntoa ( Buffer , HostIP ) ;
     printf ( "\nAdres domeny %s jest %s\n" , HostName , Buffer ) ;
   } /* if ... else */ ;
} /* DNSResolve */


void main ( )
{
  char Buffer [ 32 ] ;
  //---------------------------------------------------------------------------
  sock_init ( ) ;
  printf( "Moj adres IP = %s\n" ,
          inet_ntoa ( Buffer , gethostid ( ) ) ) ;
  printf( "Adres IP DNS = %s\n" , MY_NAMESERVER ) ;
  printf( "Adres IP GW = %s\n" , MY_GATEWAY ) ;
  printf( "\n\n" ) ;
  DNSResolve ( "microgeek.pl" ) ;
  DNSResolve ( "microgeek.com" ) ;
  DNSResolve ( "microgeek.eu" ) ;
  DNSResolve ( "elportal.pl" ) ;
  DNSResolve ( "kamami.pl" ) ;
  DNSResolve ( "btc.pl" ) ;
  DNSResolve ( "onet.pl" ) ;
  DNSResolve ( "google.com" ) ;
} /* main */
Do programu wklepuję kila różnych nazw domen (istniejące i nieistniejące). Standardowo: kompilacja, załadowanie do pamięci flash, uruchomienie daje:
Moj adres IP = 192.168.0.44
Adres IP DNS = 192.168.0.254
Adres IP GW = 192.168.0.254

Nie mozna znalezc adresu IP dla domeny microgeek.pl

Adres domeny microgeek.com jest 103.224.182.216

Adres domeny microgeek.eu jest 194.181.20.135

Adres domeny elportal.pl jest 51.255.157.203

Adres domeny kamami.pl jest 94.152.188.251

Adres domeny btc.pl jest 212.85.125.51

Adres domeny onet.pl jest 213.180.141.140

Adres domeny google.com jest 216.58.215.78

I tak przykładowo, mówimy microgeek.eu a myślimy 194.181.20.135, A przynajmniej w chwili powstawania tego tekstu tak było, bo to może się zmienić. No nic nie jest stałe i trwałe, no czysta alchemia.
Tak korciło mnie, by sprawdzić te informacje (ja wszystko sprawdzam). No więc odpalam okienko cmd:
rab08_ilu01.png
Królik twierdzi, że: Adres domeny microgeek.eu jest 194.181.20.135, ping w windozie potwierdza to. Wniosek: nie kłamie, mówi prawdę. Hmmm, właściwie, to nie opcji by mijał się z prawdą. A tak przy okazji, nie odpowiada na pingowe zaczepki. Wolno mu, w końcu nie ma obowiązku.
Analogicznie:
Microsoft Windows XP [Wersja 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

E:\microgeek>ping elportal.pl

Badanie elportal.pl [51.255.157.203] z użyciem 32 bajtów danych:

Odpowiedź z 51.255.157.203: bajtów=32 czas=58ms TTL=53
Odpowiedź z 51.255.157.203: bajtów=32 czas=58ms TTL=53
Odpowiedź z 51.255.157.203: bajtów=32 czas=45ms TTL=53
Odpowiedź z 51.255.157.203: bajtów=32 czas=54ms TTL=53

Statystyka badania ping dla 51.255.157.203:
Pakiety: Wysłane = 4, Odebrane = 4, Utracone = 0 (0% straty),
Szacunkowy czas błądzenia pakietów w millisekundach:
Minimum = 45 ms, Maksimum = 58 ms, Czas średni = 53 ms

E:\microgeek>

Zgada się: Odpowiedź z 51.255.157.203: bajtów=32 czas=58ms TTL=53Adres domeny elportal.pl jest 51.255.157.203.
Kolejna pozycja:
Microsoft Windows XP [Wersja 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

E:\microgeek>ping btc.pl

Badanie btc.pl [212.85.125.51] z użyciem 32 bajtów danych:

Odpowiedź z 212.85.125.51: bajtów=32 czas=32ms TTL=56
Odpowiedź z 212.85.125.51: bajtów=32 czas=32ms TTL=56
Odpowiedź z 212.85.125.51: bajtów=32 czas=30ms TTL=56
Odpowiedź z 212.85.125.51: bajtów=32 czas=29ms TTL=56

Statystyka badania ping dla 212.85.125.51:
Pakiety: Wysłane = 4, Odebrane = 4, Utracone = 0 (0% straty),
Szacunkowy czas błądzenia pakietów w millisekundach:
Minimum = 29 ms, Maksimum = 32 ms, Czas średni = 30 ms

E:\microgeek>

Pasuje: Badanie btc.pl [212.85.125.51]Adres domeny btc.pl jest 212.85.125.51.
Również prawdziwe, do bólu.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » sobota 21 kwie 2018, 02:00

Tak już na luzie, idzie się dogadać
Coffee Music – Relaxinghhttps://www.youtube.com/watch?v=IaLjxetQcXw

Dotychczas adresy IP były usztywnione. Rzecz jasna, czasami bywa to przeszkadzające. Powołany do istnienia byt (króliczy) może być nienazwany, taka swoista tabula raza. Jednak do egzystowania należy posiadać „imię”. W zasobach płyty CD dodanym do zestawu, natrafiłem na odpowiedni przykład, który został lekko zmodyfikowałem (kosmetyka).
Eksperyment związany z poznaniem własnej tożsamości, program:

Kod: Zaznacz cały

#class auto

#define PORTA_AUX_IO

/*
 * Pick the predefined TCP/IP configuration for this sample.  See
 * LIB\TCPIP\TCP_CONFIG.LIB for instructions on how to set the
 * configuration.
 * Config #5 = simple blank-slate DHCP, with fallbacks
 */
#define TCPCONFIG      5

/*
 * Define this symbol to force BOOTP protocol (not DHCP).  This is useful
 * when code space is tight.  You may need to specially configure your
 * DHCP server to respond to BOOTP-only clients.
 */
//#define BOOTP_ONLY

/*
 * General debugging options...
 */
//#define BOOTP_DEBUG      // Allow Dynamic C debugging in bootp.lib
//#define BOOTP_VERBOSE      // Print lots of detail
//#define ICMP_VERBOSE

/*
 * Specify information to obtain from DHCP server...
 */
#define DHCP_NUM_SMTP 1      // Get an SMTP server if possible
#define DHCP_NUM_ROUTERS 2   // Get up to 2 routers (gateways) if possible
#define DHCP_NUM_DNS  2      // Get up to 2 DNS (Domain Name System) servers if possible
#define DHCP_NUM_QOTD 2      // Get up to 2 cookie (Quote Of The Day) servers if possible
#define MAX_COOKIES 2      // Also need to tell main tcp lib (default is 1).



// Min DHCP retry interval (secs).  If not defined, defaults to 60.
#define DHCP_MINRETRY 5

// This define causes boot image file to be downloaded.  The value
// specifies the maximum number of bytes to download.  This should
// be less than about 32k to avoid running out of extended memory.
// You will need to configure your server to specify the file to
// download.
#define DHCP_USE_TFTP (3*512+5)
#define TFTP_ALLOW_BUG      // Work-around certain TFTP server upload bug

// This optional string will be sent to the DHCP server as the
// 'class identifier' of this host.  This allows the server to
// "know what it's dealing with".  There is no particular standard
// for this string, but for ease of management Z-World suggests
// colon-separated fields in the form "hardware platform:vendor:
// firmware identifier:version number".  Your DHCP server can be
// configured to recognise these strings in order to select
// appropriate parameters. [NB: it is expected that this string
// be the same for all clones, i.e. not customised for each unit
// of the same product -- the ethernet hardware address is unique
// for each unit and thus identifies particular 'individuals' to
// the DHCP server.  Think of class ID as identifying the "what" but
// not the "who"].
#define DHCP_CLASS_ID "Rabbit-TCPIP:Z-World:DHCP-Test:1.0.0"

// This macro causes the MAC address to be used as a unique client
// identifier.
#define DHCP_CLIENT_ID_MAC

#memmap xmem
#use dcrtcp.lib


/*
 * Print some of the DHCP or BOOTP parameters received.
 */
static void print_results(void)
{
   auto long tz;
   auto word i;
   char Buffer [ 20 ] ;

   printf("Network Parameters:\n");
   printf("  My IP Address = %08lX [%s]\n", my_ip_addr, inet_ntoa(Buffer,my_ip_addr)) ;
   printf("  Netmask = %08lX [%s]\n", sin_mask, inet_ntoa(Buffer,sin_mask)) ;
   if (_dhcphost != ~0UL) {
      if (_dhcpstate == DHCP_ST_PERMANENT) {
         printf("  Permanent lease\n");
      } else {
         printf("  Remaining lease = %ld (sec)\n", _dhcplife - SEC_TIMER);
         printf("  Renew lease in %ld (sec)\n", _dhcpt1 - SEC_TIMER);
      }
      printf("  DHCP server = %08lX [%s]\n", _dhcphost, inet_ntoa(Buffer,_dhcphost)) ;
      printf("  Boot server = %08lX\n", _bootphost);
   }
   if (gethostname(NULL,0))
      printf("  Host name = %s\n", gethostname(NULL,0));
   if (getdomainname(NULL,0))
      printf("  Domain name = %s\n", getdomainname(NULL,0));
   if (dhcp_get_timezone(&tz))
      printf("  Timezone (fallback only) = %ldh\n", tz / 3600);
   else
      printf("  Timezone (DHCP server) = %ldh\n", tz / 3600);
   for (i = 0; i < *_last_nameserver; i++)
      printf("  DNS server #%u = %08lX [%s]\n", i+1, def_nameservers[i], inet_ntoa(Buffer,def_nameservers[i])) ;
   if (_smtpsrv)
      printf("  SMTP server = %08lX\n", _smtpsrv);
   for (i = 0; i < _last_cookie; i++)
      printf("  Cookie server #%u = %08lX\n", i+1, _cookie[i]);
//   ip_print_ifs();
//   router_printall();
}

void main()
{
   longword st;
   longword rls;
   char bounced;
   char pboot;
   char putback;
   struct tftp_state ts;
   int status;
   word bflen;

   pboot = false;      // Not yet printed boot file
   putback = false;   // Not yet echoed boot file to server
   bounced = false;   // Not yet released/re-acquired DHCP parameters

   // Set runtime control for sock_init()...
   ifconfig(IF_DEFAULT,         // (DHCP only works on default interface)
      IFS_DHCP_TIMEOUT, 6,      // Specify timeout in seconds
      IFS_DHCP_FALLBACK, 1,   // Allow use of fallbacks to static configuration
      IFS_ICMP_CONFIG, 1,      // Also allow use of directed ping to configure (only if DHCP times out).
      IFS_END);

   printf("Starting network (max wait %d seconds)...\n", _bootptimeout);

   status = sock_init();

   switch (status) {
      default:
         break;
      case 1:
         printf("Could not initialize packet driver.\n");
         exit(1);
      case 2:
         printf("Could not configure using DHCP.\n");
         break;   // continue with fallbacks
      case 3:
         printf("Could not configure using DHCP; fallbacks disallowed.\n");
         exit(3);
   }

   if (_dhcphost != ~0UL)
      printf("Lease obtained\n");
   else {
      printf("Lease not obtained.  DHCP server may be down.\n");
      printf("Using fallback parameters...\n");
   }
   print_results();

   rls = SEC_TIMER + 90;   // In 1.5 minutes relinquish lease.

   for (;;) {

      // Check lease has not expired
      if (!tcp_tick(NULL)) {
         printf("Network down; bringing up in 2 secs...\n");
         st = SEC_TIMER + 2;
         while (SEC_TIMER < st);
         if (!(status = dhcp_acquire())) {
            printf("Network back up\n");
            print_results();
         }
         else if (status == 1) {
            printf("Network back up but with DIFFERENT IP address\n");
            print_results();
         }
         else {
            printf("Network lost.  DHCP server probably down.\n");
            exit(78);
         }
      }

      // Some time after boot, "bounce" the network (just once).
      if (!bounced && SEC_TIMER > rls) {
         bounced = true;
         //dhcp_release();
         ifconfig(IF_DEFAULT, IFS_DHCP, 0, IFS_END);
         printf("Network relinquished; re-acquiring in 3 secs...\n");
         ip_print_ifs();
         st = SEC_TIMER + 3;
         while (SEC_TIMER < st);
         //if (!(status = dhcp_acquire())) {
         if (!(status = ifconfig(IF_DEFAULT, IFS_DHCP, 1, IFS_END))) {
            printf("Lease re-acquired\n");
            print_results();
         }
         else if (status == 1) {
            printf("Hmmm... lease re-acquired with DIFFERENT IP address\n");
            print_results();
         }
         else {
            printf("Whoops!  Lost network.  DHCP server probably down.\n");
            exit(79);
         }
      }

      // When we first get the boot file, print its length.  _bootpdone is
      // a global variable which gets set to 1 if the bootfile has been
      // downloaded, 2 if there was no bootfile specified, or
      // 0 if bootfile status not yet known.
      if (!pboot && _bootpdone) {
         pboot = true;
         if (_bootpdone == 2)
            printf("No network boot file configured by server\n");
         else {
            printf("Network boot file:\n");
            if (_bootperror && _bootperror != -5)
               printf("  Error code %d: %s\n", _bootperror,
                 _bootperror == -1 ? "Server denied access" :
                 _bootperror == -2 ? "Could not contact server" :
                 _bootperror == -3 ? "Timed out" :
                   "unknown error"
                 );
            else {
               printf("  Length = %u\n", _bootpsize);
               if (_bootperror == -5)
                  printf("  File was truncated\n");
               putback = true;
            }
         }
      }

      // Once we have the boot file, echo it back to the server.  Sometimes, for
      // a length which is not an exact multiple of 512, an error condition will
      // be returned.  This happens when the server is non-RFC compliant and
      // does not wait around to ACK the last packet.  It's not our fault!
      if (putback) {
         putback = false;
         ts.state = 1;   // Write
         ts.buf_addr = _bootpdata;
         ts.buf_len = _bootpsize;
         ts.my_tid = 0;
         ts.sock = NULL;   // use DHCP one
         ts.rem_ip = 0;      // use bootp server
         ts.mode = TFTP_MODE_OCTET;
         strcpy(ts.file, "/tftpboot/echo");
         printf("Sending boot file back as %s\n", ts.file);

         // This uses the non-blocking TFTP functions, but in a blocking
         // manner.  It would be easier to use tftp_exec(), but this
         // doesn't return the server error message.
         if (!tftp_init(&ts)) {
            while ((status = tftp_tick(&ts)) > 0);   // Loop until complete
            if (!status)
               printf("Upload completed\n");
            else {
               printf("Upload failed: code %d\n", status);
               if (status == -1)
                  printf("  Message from server: %s\n", ts.file);
            }
         }
         else
            printf("Error: could not use dchp socket for tftp\n");

         // Now we do it again, using tftp_exec().
         //bflen = _bootpsize;
         //status = tftp_exec(1,_bootpdata,&bflen,1,NULL,"/tftpboot/echo2",NULL);
         //printf("echo2 uploaded: status = %d\n", status);
      }
   }
}
Pisałem o tym już wcześniej i tylko dla przypomnienia:

Kod: Zaznacz cały

#define TCPCONFIG      5
Ten zapis konfiguruje adresację do oczekiwanego wariantu (związanego z serwisem DHCP). W roli matki chrzestnej występuje mój domowy serwer DHCP, a uroczyście nadane imię jest następujące:
Starting network (max wait 6 seconds)...
Lease obtained
Network Parameters:
My IP Address = C0A8006F [192.168.0.111]
Netmask = FFFFFF00 [255.255.255.0]
Remaining lease = 86398 (sec)
Renew lease in 43198 (sec)
DHCP server = C0A800FE [192.168.0.254]
Boot server = 00000000
Timezone (fallback only) = 0h
DNS server #1 = C0A800FE [192.168.0.254]
No network boot file configured by server

No i nie da się ukryć, wszystko się zgadza. Króliczy procek dogadał się z domowym serwerem DHCP, co potwierdza świadek ping.
rab09_ilu01.png
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » niedziela 22 kwie 2018, 23:14

Cały świat u stóp
Muza lekka jak piórkohttps://www.youtube.com/watch?v=M56TEPi0u34
A może by tak coś potransmitować, rzecz jasna przez sieć na dalej niż środowisko bieżącej chałupy. Na dużą odległość, to, wiadomo, należy użyć protokołu TCP. Ach, gdyby tak sięgnąć na drugi koniec świata, tak na 400 lat świetlnych, to byłoby po byku... Nie trzeba tu wielkiej filozofii, by stwierdzić, że potrzebny jest jakiś rozmówca na drugim końcu. Mogę nawiązać połączenie TCP od króliczego zestawu do kompa na stole. Z jednej strony, to... trochę blisko, ale z drugiej strony jest do ogarnięcia, bo mogę użyć standardowego telneta lub napisać jakiś program do PC, który odbierze połączenie. Gadanie samego ze sobą... Może należy poszukać zdalnego rozmówcy, tylko kto odpowie na kontakt i będzie wystarczająco daleko. Trochę wysiłku umysłowego i … mam :arrow: serwis www.

Kod: Zaznacz cały

#define PORTA_AUX_IO

#class auto

#define TCPCONFIG 1

#use "dcrtcp.lib"

#define  DestPageName  "www.ti.com"
#define  HTTPPort      80

void main()
{
  char ReadBuffer [ 100 ] ;
  char SendBuffer [ 256 ] ;
  int bytes_read ;
  longword destIP ;
  tcp_Socket TCPSocket ;
  //---------------------------------------------------------------------------
  sock_init ( ) ;
  printf( "Poszukiwanie adresu IP dla %s\n" , DestPageName );
  destIP = resolve ( DestPageName ) ;
  if ( destIP == 0 )
  {
    printf( "Cos nie tak?\n", DestPageName );
    exit ( 1 ) ;
  } /* if */ ;
  printf ( "Adres IP=%s\n\n\n" , inet_ntoa ( ReadBuffer , destIP ) ) ;
  tcp_open ( & TCPSocket , 0 , destIP , HTTPPort , NULL ) ;
  printf("Oczekiwanie na polaczenie\n");
  while ( ! sock_established ( & TCPSocket ) && sock_bytesready ( & TCPSocket ) == -1 )
  {
    tcp_tick ( NULL ) ;
  } /* while */ ;
  strcpy ( SendBuffer , "GET /\r\n\r\n" ) ;
  printf ( "Polaczenie stabilne, wyslanie zaczepnego zaklecia:\n\n\n\n" ) ;
  sock_write ( & TCPSocket , SendBuffer , strlen ( SendBuffer ) ) ;
  do
  {
    bytes_read = sock_fastread ( & TCPSocket , ReadBuffer , sizeof ( ReadBuffer ) - 1 ) ;
    if ( bytes_read > 0 )
    {
      ReadBuffer [ bytes_read ] = '\0' ;
      printf ( "%s" , ReadBuffer ) ;
    } /* if */ ;
  } while ( tcp_tick ( & TCPSocket ) ) ;
  sock_abort ( & TCPSocket ) ;
  printf ( "\n\nPolaczenie zamkniete\n" ) ;
} /* main */
Wymyśliłem sobie, że „pogadam” sobie z jakimś kompem za kałużą. Wylosowałem sobie www.ti.com, ot tak, bez jakichkolwiek sympatii lub uprzedzeń. By było w miarę elastycznie, to w programie jest jedna stała lokalizująca zdalnego rozmówcę. Właściwie, to trudno to nazwać dialogiem, to bardziej przypomina monolog.
Nieistotne. Wysłane jest w świat coś, co jest prośbą, żądaniem (chcę dostać: GET). Po wyartykułowaniu życzenia, spodziewamy się ogromu dobra. Kompilacja, uruchomienie programu i … guzik z pętelką. Rzeczywistość ze stoickim spokojem wyraziła się: spadaj (eufemizm).
Poszukiwanie adresu IP dla www.ti.com
Adres IP=23.59.120.133


Oczekiwanie na polaczenie
Polaczenie stabilne, wyslanie zaczepnego zaklecia:


HTTP/1.0 400 Bad Request
Server: AkamaiGHost
Mime-Version: 1.0
Content-Type: text/html
Content-Length: 216
Expires: Sun, 22 Apr 2018 19:22:31 GMT
Date: Sun, 22 Apr 2018 19:22:31 GMT
Connection: close

<HTML><HEAD>
<TITLE>Bad Request</TITLE>
</HEAD><BODY>
<H1>Bad Request</H1>
Your browser sent a request that this server could not understand.<P>
Reference&#32;&#35;7&#46;e5941160&#46;1524424951&#46;0
</BODY>
</HTML>


Polaczenie zamkniete

A miało być tak pięknie. No cóż, prośba została źle skonstruowana. Zaczepne GET pochodzi z przykładowego programu. I nie działa. WTF? No trochę nerw mnie szarpnął. Tyle starań i nic. Wychodzi, że wszystko co piszą, to ściema. Ale przecież musi działać, toż to codzienność. No nie wiem co robić. Opanowanie i chłodne spojrzenie daje sugestię rozwiązania. Zawsze warto podpatrzeć jak robią to mistrzowie, oni zawsze mają rację. Za pomocą programu Ethereal podglądam jak wygląda sekretna prośba do świata przykładowo w Google Chrome (dawny Ethereal obecnie nazywa się Wireshark). No i olśnienie, to robi się inaczej. Upór jednak popłaca. Korekta w programie (istotny fragment):

Kod: Zaznacz cały

strcpy ( SendBuffer , "GET / HTTP/1.1\r\nHost: www.ti.com\r\nConnection: keep-alive\r\nAccept: text/html\r\n\r\n" ) ;
Ponowna próba. Przyszło, całe mnóstwo.
rab10_ilu01.PNG
Jak nie patrzeć, normalne zapisy w hatymelu.
rab10_ilu02.PNG
Można sięgnąć wszędzie, po prostu cały świat u stóp.
Jak ważne jest sformułowanie prośby. Czy to jest jakaś sekretna wiedza? Czy komuś zależy, by była ona dla nielicznych? Z pewnością nie należę do grupy ściemniaczy, podzieliłem się wiedzą. To fascynujące zajęcie: nieść kaganek wiedzy.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » poniedziałek 23 kwie 2018, 23:59

Najlepsze są własne ścieżki
Nutahttps://www.youtube.com/watch?v=9aF8h8r3IcU

Ostatnie eksperymenty z wiedzą książkową były... jakie były. Czasami jest tak, że wiedza książkowa nie jest warta złamanego paznokcia. Ile jest wart złamany paznokieć? Kwestia punktu widzenia. Z jednej perspektywy jest nic nie wart, z innej jest wart miliony. Przecież z tego powodu konieczne było poszerzenie własnych horyzontów, a wiedza jest bezcenna. A taka, którą jeszcze dodatkowo naumiało się stosować w praktyce jest bezcenna w kwadracie. No niby teoretycznie wszystko wiadomo, a co do czego, to dopiero doświadczenie jest prawdziwym weryfikatorem.
No więc nadszedł czas by wziąć przychodzące połączenia na siebie i być użytecznym wszystkim potrzebującym. W sieciach jest otwarcie gniazda połączeniowego do nasłuchu. Każdy, kto czegoś potrzebuje, może nawiązać połączenie do króliczego systemu. Podpierając się jedynie niezbędną dokumentacją opisującą wybrane funkcje do obsługi sieci, powstaje program, który otwiera do nasłuchu port o numerze 1024 (taki sobie wybrałem). Rzecz jasna nie obyło się bez walki, troszeczkę trzeba było. Czasem własne wyobrażenia co do cudzych rozwiązań są nietrafione, ale iteracyjnie zmierzam do celu, by wreszcie trafić w sedno.
Program wygląda następująco:

Kod: Zaznacz cały

#define PORTA_AUX_IO

#class auto

#define TCPCONFIG 1

#use "dcrtcp.lib"

#define  ListenPostNo     1024

void main()
{
  char ReadBuffer [ 100 ] ;
  tcp_Socket TCPSocket ;
  //---------------------------------------------------------------------------
  sock_init ( ) ;
  printf( "Nasluch TCP na porcie %d\n" , ListenPostNo );
  for ( ; ; )
  {
    tcp_listen ( & TCPSocket , ListenPostNo , 0L , 0 , NULL , 0 ) ;
    while ( ! sock_established ( & TCPSocket ) && sock_bytesready ( & TCPSocket ) == -1 )
    {
      tcp_tick ( NULL ) ;
    } /* while */ ;
    sock_mode ( & TCPSocket , TCP_MODE_ASCII ) ;
    puts ( "****Polaczenie\n" ) ;
    do
    {
      if ( sock_bytesready ( & TCPSocket ) >= 0 )
      {
        sock_gets ( & TCPSocket , ReadBuffer , sizeof ( ReadBuffer ) - 1 ) ;
        printf ( "%s\n" , ReadBuffer ) ;
        sock_write ( & TCPSocket , ReadBuffer , strlen ( ReadBuffer ) ) ;
        sock_write ( & TCPSocket , "\r\n" , 2 ) ;
      } /* if */ ;
     } while ( tcp_tick ( & TCPSocket ) ) ;
     puts ( "****Rozlaczenie\n" ) ;
     sock_close( & TCPSocket );
  } /* for */ ;
} /* main */
Program odbiera coś z sieci, przedrukowuje to do strumienia wyjściowego stdio oraz robi „echo” (wysyła do nadawcy to co odebrał). Teraz otwierają się wręcz niewiarygodnie szerokie możliwości zastosowań. Może jakiś dialekt SCPI, pomyślę o tym.
Na teraz raport z badań. Do połączenia z króliczym światem używałem program HyperTerminal skonfigurowany do połączeń TCP. Już jego uruchomienie implikuje nawiązanie połączenia, o czym uprzejmie donosi króliczy procek via strumień stdio.
rab11_ilu01.PNG
Program ten (HyperTerminal) został skonfigurowany następująco:
rab11_ilu02.PNG
Pisząc coś w programie HyperTerminal można dokonać pewnego spostrzeżenia (może kiedyś do czegoś się przyda, na razie informacje się gromadzą w głowie). Program ten wysyła dane dopiero po użycia klawisze Enter, ponieważ pisany tekst pojawia się dopiera po naciśnięciu tego klawisza (dane echa mają dodaną sekwencję zmiany wiersza i każdy znak byłby pisany w oddzielnym wierszu).
rab11_ilu03.PNG
Kliknięcie na ikonkę rozłączenia powoduje rozłączenie połączenia. Kolejny klik,
rab11_ilu04.PNG
i następuje połączenie. I tak można się bawić...
rab11_ilu05.PNG
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » piątek 27 kwie 2018, 13:30

Kolejny szczyt zdobyty
Chiny, ciekawy świat na wschodziehttps://www.youtube.com/watch?v=3MfiVfoa3wo
Tak eksperymentując w temacie ethernetu w mikrokontrolerach zaczyna mi trochę wychodzić, pomimo że jeszcze trochę przeszkód pozostaje, ale powoli wszystko idzie ku lepszemu. Zapewne króliczy świat przyjął moje przeprosiny :), więc dziękuję i szacun. Po eksperymentach związanych z pobieraniem stron, wręcz naturalnym jest serwowanie stron. Nie to, że będę chciał stworzyć jakiś wielki serwis, ale może, w przyszłości, kto wie? Na razie to urodził mi się taki pomysł, by via internet (czytaj: strony www) serwować przykładowo dane pomiarowe. Pod króliczy procek można podłączyć różne pomierniki, nawet vintagowe i spokojnie oglądać dane pomiarowe. Taki mój patent.
W zasobach króliczych przykładów jest przykład serwera stron www. Finalnie program przedstawia się następująco (już po moich zmianach):

Kod: Zaznacz cały

#class auto
#define PORTA_AUX_IO

#define TCPCONFIG 1

#define TIMEZONE        -8

#memmap xmem
#use "dcrtcp.lib"
#use "http.lib"

#ximport "samples/tcpip/http/pages/static.html"    index_html
#ximport "samples/tcpip/http/pages/rabbit1.gif"    rabbit1_gif
#ximport "samples/tcpip/http/pages/button.html"       key_html

const HttpType http_types[] =
{
   { ".html", "text/html", NULL},
   { ".gif", "image/gif", NULL}
};

const HttpSpec http_flashspec[] =
{
   { HTTPSPEC_FILE,  "/",                     index_html,    NULL, 0, NULL, NULL},
   { HTTPSPEC_FILE,  "/index.html",    index_html,    NULL, 0, NULL, NULL},
   { HTTPSPEC_FILE,  "/rabbit1.gif",   rabbit1_gif,   NULL, 0, NULL, NULL},
   { HTTPSPEC_FILE,  "/key.html",      key_html,      NULL, 0, NULL, NULL},
};

void main()
{
   sock_init();
   http_init();
   tcp_reserveport(80);
   while (1) {
      http_handler();
   }
}
Kompilator wciąga w kod programu zawartość odpowiednich plików reprezentujących strony. Obrazek również jest wkompilowany.
Do programu są wciągnięte następujące treści z zewnętrznych plików:
  • obrazek:
    rabbit1.gif
  • plik odpowiadający stronie głównej:

    Kod: Zaznacz cały

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML//EN">
    <HTML>
    <HEAD>
       <TITLE>Kroliczy swiat serwuje innym swoje mozliwosci</TITLE>
    </HEAD>
    <BODY topmargin="0" leftmargin="0" marginwidth="0" marginheight="0"
       bgcolor="#00FF00" link="#009966" vlink="#FFCC00" alink="#006666">
    <CENTER>
       <img SRC="rabbit1.gif">
       <BR>
       <BR>
       <BR>
       Jak tu klikniesz, to przejdziesz do innego swiata: <a href="button.html">KLIK</A>
    </CENTER>
    </BODY>
    </HTML>
  • plik odpowiadający kliknięciu na KLIK:

    Kod: Zaznacz cały

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML//EN">
    <HTML>
    <HEAD>
       <TITLE>Kroliczy swiat serwuje innym swoje mozliwosci</TITLE>
    </HEAD>
    <BODY topmargin="0" leftmargin="0" marginwidth="0" marginheight="0"
       bgcolor="#00FF00" link="#009966" vlink="#FFCC00" alink="#006666">
    <CENTER>
       <img SRC="rabbit1.gif">
       <BR>
       <BR>
       <BR>
       To jest nastepna strona. Uzyj przycisku BACK by wrocic.
    </CENTER>
    </BODY>
    </HTML>
Standardowa akcja z kompilacją i ładowaniem kodu programu do procka. Odpalam przeglądarkę, która do tej pory była zajęta jedynie operą Pucciniego. Po otwarciu właściwej strony, mamy:
rab12_ilu01.PNG
Bingo. Nawet jak najedzie się myszką na napis KLIK to jest to co powinno być.
rab12_ilu02a.PNG
No więc nie ma co się zastanawiać, jedziemy.
rab12_ilu03.PNG
UPS. A o co chodzi? Niby wszystko jest OK, a nie działa. Mnóstwo eksperymentów, by znaleźć rozwiązanie. Wiadomo co ma być, nie wiadomo jak do tego dojść. Normalnie ręce opadają. Chyba będę potrzebował pomocy. Jestem wdzięczny dla pamięci flash, że miała tyle cierpliwości, bo wszystko ma swój limit. Liczbę przeprogramowań chyba osiągnąłem.
Niewiele brakowało, by wszystko potłuc o kant. Już miałem takie doświadczenia, swego czasu rozwaliłem własną klawiaturę o kant stołu. Klawiatura umarła. Przecież nie o to chodzi, wspieram każdą formę egzystencji (klawiatury też). Chyba będę potrzebował jakiejś pomocy. Pomocy...
Zrobiłem sobie herbatę, w prezentowym kubku z WAAR team. Chwila spokoju. A może to...
Kolejna poprawka softu, kompilacja itd.
rab12_ilu04.PNG
Działa. Yes, yes, yes. A tak niewiele brakowało, wszystko wisiało na jednym włosku. Działa, co ulga. Ogrom pracy nie poszedł w gwizdek. Spokojnie patrzę na kubek. Co za przypadek, jest tak obrócony, że widać napis TEAM. Grunt to praca zespołowa.
Lody pokonane. Technologia poznana, już wiem jak to się robi. Wszystko jest do zrobienia, nie ma rzeczy niemożliwych. Jak banalnie jest to proste, ale widocznie tak miało być. TEAM. Wystarczy poprosić a ktoś/coś zrobi resztę.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » poniedziałek 30 kwie 2018, 12:30

Nocna praca
...zbierając wiatr...https://www.youtube.com/watch?v=2s46P7udKh4

Wymyśliłem sobie, że można by porozumieć się z króliczego proca z bazą danych. Moim zdaniem to świetna koncepcja by móc lokować własne dane w bazie danych. Trzeba tylko uzyskać do niej dostęp, a to trochę wymaga badań i zachodu.
Przykładowo dotychczasowe moje zabawy z bazą MySQL nie były zbyt skomplikowane, ot nie było takich potrzeb. Po prawdzie, to początki związane były z żółtymi kredensami, gdzie bazodanowe operacje były wręcz prymitywne. Jednak z tego została pewna wiedza, która powoli ewoluowała. Wiadomo, że w przypadku baz danych (a tak jest w MySQL), komunikacja z bazą odbywa się via TCP. Skoro tak, to co powstrzymuje w realizacji takiej komunikacji z króliczego procka. Pomiar czegokolwiek (cyfrowy/analogowy) generuje dane. Z kolei te dane są transportowane do centrum bazowego przez otwór jakim jest numer portu (w MySQL jest to 3306). W większości zastosowań ten ruch sieciowy jest adresowany do localhost. Pierwsza próba okazała się nieskuteczna. Wireshark (zainstalowałem nawet najnowszą wersję) nie umożliwia monitorowania ruchu dla localhost. Problem, ale na każdą koncepcję daje się znaleźć anty_koncepcję. Sięgałem do bazy z innego komputera, więc ruch sieciowy musiał przejść przez kartę sieciową, a ta już dała się opanować.
Tu również okazało się, że nie jest to tak hop siup. Baza danych musiała być odpowiednio poczarowana, by pozwoliła na dostęp z zewnątrz. Cała nocka zeszła mi na czarowaniu. Finalnie jakieś dane trafiły do bazy. Taki eksperyment, dotyczył prostej tabeli w bazie zawierającej trzy kolumny:
rab13_00.PNG
Napisany w czymkolwiek program uruchomiony z innego komputera realizował zapis jednej danej z pomiaru (o symbolu T11) o wartości 12,12. Monitorowanie ruchu na karcie sieciowej wygenerowało następujące informacje:
  • taki connect do bazy danych: baza danych nazywa się 'homeauto', logujący się użytkownik to 'user', podane jest hasło jest 'geek', może ktoś ma ochotę i pomoże w rozwaleniu tego muru,
    rab13_01.PNG
  • ustalenie „alfabetu” znaki kodowane w UTF8,
    rab13_02.PNG
  • jakieś zaklęcia, których jeszcze nie rozumiem,
    rab13_03.PNG
    rab13_04.PNG
  • zaklęcie select, to już mamy język sql,
    rab13_05.PNG
  • i najbardziej interesujące: insert.
    rab13_09.PNG
Po tym zabiegu dane trafiły do bazy. Z czasem urosną do dużych rozmiarów.
To takie zapowiedzi możliwości, które będę przenosił na inne platformy sprzętowe. Jest do pokonania hasło, które jest szyfrowane. Może da się je usunąć, tak skonfigurować bazę, by nie wymagała hasła. Przecież tak bliskie kontakty powinny być oparte o zaufanie, w końcu to domowa baza danych, która będzie skrywać jedynie domowe sekrety. Z pewnością uda mi się tego dokonać.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

Awatar użytkownika
xor
User
User
Posty: 169
Rejestracja: poniedziałek 05 wrz 2016, 21:44

Re: RABBIT 2000

Postautor: xor » poniedziałek 30 kwie 2018, 19:36

Manewry z wiresharkiem są IMHO niepotrzebne. Na stronach MySQLa można znależć zarówno opis protokołu komunikacji (https://dev.mysql.com/doc/dev/mysql-ser ... TOCOL.html) jak i kody źródłowe Connectorów (https://www.mysql.com/products/connector/)
W charakterze ciekawostki - istnieje klient MySqla na Arduino: https://launchpad.net/mysql-arduino/+download

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

Re: RABBIT 2000

Postautor: gaweł » poniedziałek 30 kwie 2018, 20:14

xor pisze:Manewry z wiresharkiem są IMHO niepotrzebne. Na stronach MySQLa można znależć zarówno opis protokołu komunikacji (https://dev.mysql.com/doc/dev/mysql-ser ... TOCOL.html) jak i kody źródłowe Connectorów (https://www.mysql.com/products/connector/)
W charakterze ciekawostki - istnieje klient MySqla na Arduino: https://launchpad.net/mysql-arduino/+download

Serdecznie ci dziękuję xor za cenne informacje, w sposób niezamierzony wiedza sama spadła z nieba ;) . Ściągnę zaproponowane pliki i przeanalizuję. Jednak mi chodzi o wiedzę podstawową, czyli jak to się robi własnymi rękoma. Pokazane sterowniki ODBC są dla windozy, mi chodzi o funkcjonalność dla mikrokontrolera. Sama baza stoi na windozie lub na jakimś linuchu i ma już odpowiednie sterowniki w sensie obsługi przychodzących połączeń. Interesująca jest druga strona: klienta dla bazy danych, to dla mnie jest wielki potencjał, mus produkować kody dla bazy danych i w sumie wymieniać informacje z bazą. Jak na razie to ćwiczenia są w C. Proponujesz arduino, to koncepcja warta wypróbowania. Na razie eksperymenty są w oparciu o procek RABBIT3000. W zanadrzu mam jeszcze hardvare bazujące na prockach ARM, i tam jest niewykluczone, że koncepcja z arduino będzie przydatna. Nie zaprzeczam, że programowanie w języku C będzie musiało odejść na drugi plan a na wierzch wypłynie filozofia arduino. W sumie to kierunek wart sprawdzenia, że tak powiem: idzie nowe.

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

Awatar użytkownika
xor
User
User
Posty: 169
Rejestracja: poniedziałek 05 wrz 2016, 21:44

Re: RABBIT 2000

Postautor: xor » poniedziałek 30 kwie 2018, 20:39

Nie proponuję arduino. Chodzi o to, że wydaje mi się, iż materiały udostępnione przez MySQLa umożliwiają zbudowanie swojego klienta na swoją platformę. Klient na Arduino jest tylko przykładem, i dowodem, że ktoś to zrobił na platformę, wydawało by się, nie nadającą się do takich zabaw. Więc dlaczego by nie zrobić tego na królika? :-)
Przy okazji: w kodach źródłowych powinieneś znaleźć metodę hashowania hasła, albowiem _wydaje_ mi się, że ustawienie dostępu do MySQL bez hasła może być nawet niemożliwe.
Nasuwają mi się jeszcze inne myśli ale to Twoja zabawa więc się nie wtrącam :-)

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

Re: RABBIT 2000

Postautor: gaweł » poniedziałek 30 kwie 2018, 21:06

xor pisze:Nie proponuję arduino. Chodzi o to, że wydaje mi się, iż materiały udostępnione przez MySQLa umożliwiają zbudowanie swojego klienta na swoją platformę. Klient na Arduino jest tylko przykładem, i dowodem, że ktoś to zrobił na platformę, wydawało by się, nie nadającą się do takich zabaw. Więc dlaczego by nie zrobić tego na królika? :-)

Super, to dobrze się zrozumieliśmy. Dobry przykład jest najlepszą inspiracją.

xor pisze:Przy okazji: w kodach źródłowych powinieneś znaleźć metodę hashowania hasła, albowiem _wydaje_ mi się, że ustawienie dostępu do MySQL bez hasła może być nawet niemożliwe.

I to jest cenna informacja. Tak jak napisałem, przeanalizuję to. Na razie nie wiem kiedy to będę miał opanowane, ale dążę do tego.

xor pisze:Nasuwają mi się jeszcze inne myśli ale to Twoja zabawa więc się nie wtrącam :-)

Każdy może coś wnieść. Po to jest to forum. Jest tylko jeden warunek, bez udowadniania swoich racji, z poszanowaniem innych, tak na luzie bez egoizmu. Koncepcje wartościowe zawsze znajdą dogodny grunt.

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

Awatar użytkownika
piotrek
User
User
Posty: 155
Rejestracja: niedziela 05 lis 2017, 02:46

Re: RABBIT 2000

Postautor: piotrek » wtorek 01 maja 2018, 23:36

O nie, tylko nie arduino. Taki fajny sprzęcik jak Rabbit powinien leżeć jak najdalej od wszystkiego co związane z arduino. Uważam, że za dużo wszędzie arduino i mam poważne obawy, że już niedługo nie będzie elektroniki tylko arduino :)

gaweł Jeśli chodzi o akwizycję danych nie zastanawiałeś się nad zastosowaniem HTTP do transferu zamiast mocowania się z "natywnym" protokołem MySql ? W poprzednich postach pokazałeś jak prosto w tym środowisku wysłać żądanie za pomocą metody GET. Implementując obsługę metod POST/PUT/GET uzyskasz interfejs bazujący na konwencji REST. Do tego jakaś biblioteczka do obsługi formatu JSON i otrzymasz coś co może "gadać" z różnymi serwisami, np z pogodą, czasu itd. Oczywiście jeśli chodzi o samo utrwalanie danych w bazie trzeba jeszcze postawić jakąś aplikację z obsługą REST na serwerze, ale to nie powinien być większy problem bo w gotowych przykładów w sieci jest sporo czy to dla Javy/Springa czy PHP.

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

Re: RABBIT 2000

Postautor: gaweł » środa 02 maja 2018, 10:43

piotrek pisze:O nie, tylko nie arduino. Taki fajny sprzęcik jak Rabbit powinien leżeć jak najdalej od wszystkiego co związane z arduino.

Jak do tej pory konsekwentnie trzymam się tej koncepcji, chyba nie trzeba tego udowadniać :)

piotrek pisze:gaweł Jeśli chodzi o akwizycję danych nie zastanawiałeś się nad zastosowaniem HTTP do transferu zamiast mocowania się z "natywnym" protokołem MySql ? W poprzednich postach pokazałeś jak prosto w tym środowisku wysłać żądanie za pomocą metody GET. Implementując obsługę metod POST/PUT/GET uzyskasz interfejs bazujący na konwencji REST. Do tego jakaś biblioteczka do obsługi formatu JSON i otrzymasz coś co może "gadać" z różnymi serwisami, np z pogodą, czasu itd. Oczywiście jeśli chodzi o samo utrwalanie danych w bazie trzeba jeszcze postawić jakąś aplikację z obsługą REST na serwerze, ale to nie powinien być większy problem bo w gotowych przykładów w sieci jest sporo czy to dla Javy/Springa czy PHP.

Zajmujesz się wiedźmiństwem i przepowiadasz przyszłość? Taki mam plan, nawet mogę się o to założyć :lol: (i tym razem nie przegrać), tylko kto "przetnie". Już wiem, sam przetnę. No to przecinam.
W części zatytułowanej "Zdobywanie szczytów" jest początek koncepcji. Pracuję na zdobyciem kolejnego. Będzie zaj...iście. Potrzebna jest tylko cierpliwość.

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

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

Re: RABBIT 2000

Postautor: gaweł » poniedziałek 14 maja 2018, 22:34

Istotny jest progress bar
...dla twojego dobra przecież, towarzyszę ci po świecie...https://www.youtube.com/watch?v=a8pFEEiSFPU
Po ostatnich sukcesach w pokonywaniu trudności, nastała nieoczekiwana chwila nostalgii. No cóż, nie wszystko składa się tak jak byśmy chcieli. To stanowi dodatkowy, kolejny doping do zwiększenia wysiłków w poszukiwaniu rozwiązania i konsensusu. Zaprawiony ostatnio w bojach ruszam na kolejną wyprawę na kosmiczne wyżyny możliwości technologicznych małych procków. W końcu 8-bitowy procek to maleńka kruszynka w stosunku do bezmiaru możliwości oferowanych przez uniwersum. Ważne jest tylko by nie pogubić się w meandrach możliwości.
Ostatnio jeden z moich znajomych zachciał w jakiś elegancki sposób być informowany o stanie automatyki (konkretnie chodzi o opomiarowanie temperatury w systemie CO). Prawdę mówiąc sam do końca nie bardzo wiedział co chce, jakoś często ostatnio występująca postawa. Tu przypominają mi się sytuacje, gdzie kilkanaście … kilkadziesiąt lat temu brałem udział w realizacji sporych tematów, gdzie zainteresowany klient/użytkownik nie bardzo wiedział co dokładnie chce. Instalacja systemu zbudowanego z kilkudziesięciu połączonych komputerów … a klient potrafi jedynie określić, że „chce mieć dobrze”. Jedynym rozwiązaniem jest zrozumieć specyfikę klienta, czyli chodzić za nim i patrzeć co robi, patrzeć mu na ręce. Zatrudnić się w docelowym, obcym miejscu na jakiś czas i pracować ramię w ramię w tubylcami. Do daje pogląd i wiedzę. Dzisiaj już nikt chyba tak nie robi. Twórcy systemów pod klucz są chyba bardziej zainteresowani efektem finansowym niż zadowoleniem kontrahenta. :( . Takie podejście do tematu z czasem wyrobiło u mnie umiejętność przewidywania cudzych potrzeb, wiem czego ktoś potrzebuje zanim on o tym pomyśli. Śmieszne :D .
Wracając do pomiarów analogowych w systemie CO, swoista prekognicja, pozwoliła mi zaproponować zbudowanie serwera www, z którym będzie mógł się połączyć choćby ze współczesnego telefonu komórkowego. Eksperymenty czas zacząć. Prezentowany tekst dotyczy koncepcji serwowania a dane pomiarowe są „symulowane”, w końcu jest to obecnie najmniej istotna rzecz. Obecnie nic nie liczy się bardziej niż opanowanie osobliwej technologii. By móc być gotowym na wszystko należy obecnie silnie skupić się na wybranych elementach. To pozwoli znaleźć drogę do celu.
Metodą prób i błędów (a było ich całkiem sporo) i nie było kogo zapytać, niejako skazany jedynie na siebie, dopracowałem się takiego rozwiązania (może nie jest ono idealne ale jest na miarę bieżących potrzeb).

Kod: Zaznacz cały

#define PORTA_AUX_IO

#class auto

#define TCPCONFIG 1

#use "dcrtcp.lib"

const char WebPageSrc1 [ ] = "<html>\n<head>\n<meta http-equiv=\"refresh\" ….
const char WebPageSrc2 [ ] = "</head>\n<body bgcolor=\"#3030A0\" ….
const char WebPageSrc3 [ ] = "<p><b>System pomiarowy: SOLARIS [www.solaris-...
const char WebPageSrc4 [ ] = "</b></p>\n<table bgcolor=\"#ff0000\" border=\"5\"...
const char WebPageSrc5 [ ] = "\" border=\"0\" cellpadding=\"0\"....
const char WebPageSrc6 [ ] = "<td width=\"20%\">0%</td>\n<td width=\"20%\...
const char WebPageSrc7 [ ] = "<p>UWAGA, przy osiagnieciu stanu krytycznego (….
#define  ListenPostNo     80
void main()
{
  char ReadBuffer [ 100 ] ;
  char WebPage [ 2048 ] ;
  tcp_Socket TCPSocket ;
  unsigned short AnalogData ;
  char Number [ 10 ] ;
  //---------------------------------------------------------------------------
  sock_init ( ) ;
  printf( "Nasluch TCP na porcie %d\n" , ListenPostNo );
  AnalogData = 10 ;
  for ( ; ; )
  {
    tcp_listen ( & TCPSocket , ListenPostNo , 0L , 0 , NULL , 0 ) ;
    while ( !sock_established(&TCPSocket) && sock_bytesready(&TCPSocket) == -1 )
    {
      tcp_tick ( NULL ) ;
    } /* while */ ;
    sock_mode ( & TCPSocket , TCP_MODE_ASCII ) ;
    puts ( "****Polaczenie\n" ) ;
    for ( ; ; )
    {
      if ( sock_bytesready ( & TCPSocket ) >= 0 )
      {
        sock_gets ( & TCPSocket , ReadBuffer , sizeof ( ReadBuffer ) - 1 ) ;
        if ( ( ReadBuffer [ 0 ] == 'G' ) && ( ReadBuffer [ 1 ] == 'E' ) &&
             ( ReadBuffer [ 2 ] == 'T' ) && ( ReadBuffer [ 3 ] == ' ' ) )
        {
          sprintf ( Number , "%d" , AnalogData ) ;
          printf ( "Prezentacja wartosci pomiarowej= %s\n" , Number ) ;
          sock_write ( & TCPSocket , WebPageSrc1 , strlen ( WebPageSrc1 ) ) ;
          sock_write ( & TCPSocket , WebPageSrc2 , strlen ( WebPageSrc2 ) ) ;
          sock_write ( & TCPSocket , WebPageSrc3 , strlen ( WebPageSrc3 ) ) ;
          sock_write ( & TCPSocket , Number , strlen ( Number ) ) ;
          sock_write ( & TCPSocket , WebPageSrc4 , strlen ( WebPageSrc4 ) ) ;
          sock_write ( & TCPSocket , Number , strlen ( Number ) ) ;
          sock_write ( & TCPSocket , WebPageSrc5 , strlen ( WebPageSrc5 ) ) ;
          sock_write ( & TCPSocket , WebPageSrc6 , strlen ( WebPageSrc6 ) ) ;
          sock_write ( & TCPSocket , WebPageSrc7 , strlen ( WebPageSrc7 ) ) ;
          AnalogData += 44 ;
          if ( AnalogData >= 500 )
            AnalogData -= 500 ;
          break ;
        } /* if */ ;
      } /* if */ ;
      tcp_tick ( & TCPSocket ) ;
     } /* for */ ;
     puts ( "****Rozlaczenie\n" ) ;
     sock_close( & TCPSocket );
  } /* for */ ;
} /* main */
Powyższy program serwuje następującą stronę www (jako szkielet koncepcji, którą należy zwielokrotnić, po wydobyciu danych w czeluści piekieł elektroniki pomiarowej przejść do kolejnej, później kolejnej i tak dalej z określonym priorytetem działań aż wyszarpnę wszystkie).

Kod: Zaznacz cały

<html>
<head>
<meta http-equiv="refresh" content="5">
<title>RABBIT 2000 - dynamiczne serwowanie strony</title>
</head>
<body bgcolor="#3030A0" text="#FFFF00">
<p><b><font color="#FFFFFF" size="6"><i>Witaj Kamilo przy kompie,<br>sterowanie i pomiary, domowa automatyka</i></font></b></p>
<p><b>System pomiarowy: SOLARIS [www.solaris-rozwoj....pl/liczba-9]</b></p>
<p><b>Pomiar nocnej wilgoci: wartosc [0..500]=!!XX!!</b></p>
<table bgcolor="#ff0000" border="5" cellpadding="0" cellspacing="0" width="500">
<tr><td><table width="!!XX!!" border="0" cellpadding="0" cellspacing="0">
<tr><td bgcolor="#00ff00">&nbsp;</td></tr>
</table></td></tr>
</table>
<table border="0" width="540">
<tr>
<td width="20%">0%</td>
<td width="20%">25%</td>
<td width="20%">50%</td>
<td width="20%">75%</td>
<td width="20%">100%</td>
</tr>
</table>" ;
<p>UWAGA, przy osiagnieciu stanu krytycznego (90%) nastapi wybuch i "odlot w kosmos".</p>
</body>
</html>
gdzie !!XX!! (występuje w dwóch miejscach) jest znakową wartością odpowiadającą wielkości pomiarowej wstawianą dynamicznie przez program do zawartości serwowanej strony. Strona automatycznie odświeża się co 5 sekund, nic nie trzeba robić, wszystko samo przychodzi.
rab14_01.png
Wartość pomiarowa po odczycie jest zwiększana o ileś (nieistotne obecnie) i działa na okrętkę. Po dojściu do górnej granicy jest obcinana by nastąpił powrót do miejsca, gdzie się zaczyna od nowa.
mvi_6726.mp4
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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

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

Re: RABBIT 2000

Postautor: gaweł » piątek 18 maja 2018, 23:03

Powrót do domu
(już nie jestem w lesie)

Czas się pożegnać ze starym, idzie nowe...https://www.youtube.com/watch?v=g3ENX3aHlqU
No idzie mi coraz lepiej, choć, muszę przyznać nie bez problemów. W zestawie z króliczym procem zawarta jest możliwość pomiarów analogowych. Chociaż sam przetwornik nie jest integralną częścią proca, jednak analogowo coś tam mierzy. Samego proca wspiera niezawodny towarzysz z obcego świata ADS7870 (w końcu Texas Instruments to nie Rabbit Semiconductor).
rab15_ilu01.jpg
W sumie nie jest to istotne, ważna jest współpraca, czyli praca w grupie. Już oczami wyobraźni widziałem działający system, już … prawie było gotowe. Zmieniła się mi koncepcja. Będą zastosowane pomierniki analogowe. No nie stanowi to problemu, wymaga ponownie włożenia jakiegoś wysiłku w opanowanie sprawy. Cóż tak często bywa, że już coś prawie mamy, a to nam się ponownie wymyka.
Memu kooperantowi, który nie przepada za owocami, zmieniła się wizja. Miały być Dallasy 1-wire, będą analogi. Nie wszyscy są świadomi występowania rzeczywistych problemów, jednak to nie zwalnia z przewidywania potencjalnych zagrożeń. One występują bez względu na zapatrywania.
Chwilowo, by opanować problemy stworzyłem jakąś tam prowizorkę. Do analogowych pomiarów podpiąłem na krótko jakieś sygnały analogowe. Obecnie jest krótki dystans, później trzeba będzie to doprowadzić jakimiś dłuższymi przewodami. Będą musiały być ekranowane. W końcu ochrona delikatnych struktur pomiarowych jest bardzo istotna. Moim zadaniem jest ochronić to w agresywnym środowisku, ileż tu występuje zakłóceń. Na tym kawałeczku jest to bardzo istotne. Prawdę mówiąc nie wiem jeszcze jak to zrobić, ale coś wymyślę. Jestem uparty → w końcu znak zodiaku do czegoś zobowiązuje (Aries).
rab15_ilu02.jpg
W oprogramowaniu nie ma zbyt rewolucyjnych zmian. Do programu została wpiętą obsługa analogowych pomiarów i zostały uelastycznione algorytmy generowania zawartości strony www (świat zaczyna robić się na kolorowo).
Kilka zrzutów z ekranu:
rab15_ilu10.png
rab15_ilu11.png
rab15_ilu12.png

Kod: Zaznacz cały

define PORTA_AUX_IO

#class auto

#define TCPCONFIG 1

#use "dcrtcp.lib"

#define  ListenPostNo     80

#define NUMSAMPLES        4
#define GAINSET GAIN_1      //other gain macros
                           //GAIN_1
                           //GAIN_2
                           //GAIN_4
                           //GAIN_5
                           //GAIN_8
                           //GAIN_10
                           //GAIN_16
                           //GAIN_20

const char WebPageSrc1 [ ] = "<html>\n<head>\n<meta http-equiv=\"refresh\" content=\"5\">\n<title>RABBIT 2000 -....
const char WebPageSrc2 [ ] = "<body bgcolor=\"#3030A0\" text=\"#FFFF00\">\n<p><b>...
const char WebPageSrc3 [ ] = "<i>Witaj Koles z microgeek.eu przy kompie,<br>...
//-------------
const char WebPageSrc4 [ ] = "<b>Dane pomiarowe: " ;
//        <data>
const char WebPageSrc5 [ ] = "</b><table bgcolor=\"#ffffff\" border=\"5\"...
//        <data>
const char WebPageSrc6 [ ] = "\" border=\"0\" cellpadding=\"0\"...
//        <color>
const char WebPageSrc7 [ ] = "\">&nbsp;</td></tr>\n</table></td></tr>\n</table>\n" ;
//-------------
const char WebPageSrc8 [ ] = "</body>\n</html>\n" ;


unsigned int sample_ad ( int channel , int num_samples )
{
  unsigned long rawdata ;
  unsigned int sample ;
  unsigned int cmd ;
  //---------------------------------------------------------------------------
  //convert channel and gain to ADS7870 format
  // in a direct mode
  cmd = 0x80 | ( GAINSET * 16 + ( channel | 0x08 ) ) ;
  for ( rawdata = 0 , sample = num_samples ; sample > 0 ; sample-- )
  {
    rawdata += ( long ) anaInDriver ( cmd , 12 ) ;
  } /* for */ ;
  rawdata = rawdata / num_samples ;
  rawdata /= 5 ;
  return ( ( unsigned int ) rawdata ) ;
} /* sample_ad */


char HexChar ( unsigned long int Col )
{
  switch ( Col )
  {
    case 0 :
      return '0' ;
    case 1 :
      return '1' ;
    case 2 :
      return '2' ;
    case 3 :
      return '3' ;
    case 4 :
      return '4' ;
    case 5 :
      return '5' ;
    case 6 :
      return '6' ;
    case 7 :
      return '7' ;
    case 8 :
      return '8' ;
    case 9 :
      return '9' ;
    case 10 :
      return 'a' ;
    case 11 :
      return 'b' ;
    case 12 :
      return 'c' ;
    case 13 :
      return 'd' ;
    case 14 :
      return 'e' ;
    case 15 :
      return 'f' ;
  } /* switch */ ;
} /* HexChar */


void main()
{
  char ReadBuffer [ 100 ] ;
  char WebPage [ 2048 ] ;
  tcp_Socket TCPSocket ;
  char Number [ 10 ] ;
  int Loop ;
  unsigned int ad_inputs [ 7 ] ;
  long int Colors [ 7 ] ;
  //---------------------------------------------------------------------------
  brdInit ( ) ;
  sock_init ( ) ;
  printf( "Nasluch TCP na porcie %d\n" , ListenPostNo );
  Colors [ 0 ] = 0xffff00 ;
  Colors [ 1 ] = 0x80ffff ;
  Colors [ 2 ] = 0x40bf80 ;
  Colors [ 3 ] = 0x0040ff ;
  Colors [ 4 ] = 0xff0000 ;
  Colors [ 5 ] = 0xffbf00 ;
  Colors [ 6 ] = 0x0075ff ;
  anaIn ( 0 , SINGLE , GAINSET ) ;
  for ( ; ; )
  {
    tcp_listen ( & TCPSocket , ListenPostNo , 0L , 0 , NULL , 0 ) ;
    while( !sock_established(&TCPSocket) && sock_bytesready(&TCPSocket) == -1 )
    {
      tcp_tick ( NULL ) ;
    } /* while */ ;
    sock_mode ( & TCPSocket , TCP_MODE_ASCII ) ;
    puts ( "****Polaczenie\n" ) ;
    for ( ; ; )
    {
       for ( Loop = 0 ; Loop < 6 ; Loop ++ )
       {
         ad_inputs [ Loop ] = sample_ad ( Loop , NUMSAMPLES ) ;
       } /* for */ ;
      if ( sock_bytesready ( & TCPSocket ) >= 0 )
      {
        sock_gets ( & TCPSocket , ReadBuffer , sizeof ( ReadBuffer ) - 1 ) ;
        if ( ( ReadBuffer [ 0 ] == 'G' ) && ( ReadBuffer [ 1 ] == 'E' ) &&
             ( ReadBuffer [ 2 ] == 'T' ) && ( ReadBuffer [ 3 ] == ' ' ) )
        {
          sock_write ( & TCPSocket , WebPageSrc1 , strlen ( WebPageSrc1 ) ) ;
          sock_write ( & TCPSocket , WebPageSrc2 , strlen ( WebPageSrc2 ) ) ;
          sock_write ( & TCPSocket , WebPageSrc3 , strlen ( WebPageSrc3 ) ) ;
          for ( Loop = 0 ; Loop < 6 ; Loop ++ )
          {
            sprintf ( Number , "%d" , ad_inputs [ Loop ] ) ;
            sock_write ( & TCPSocket , WebPageSrc4 , strlen ( WebPageSrc4 ) ) ;
            sock_write ( & TCPSocket , Number , strlen ( Number ) ) ;
            sock_write ( & TCPSocket , WebPageSrc5 , strlen ( WebPageSrc5 ) ) ;
            sock_write ( & TCPSocket , Number , strlen ( Number ) ) ;
            sock_write ( & TCPSocket , WebPageSrc6 , strlen ( WebPageSrc6 ) ) ;
            Number [ 0 ] = HexChar ( ( Colors [ Loop ] & 0xF00000 ) >> 20 ) ;
            Number [ 1 ] = HexChar ( ( Colors [ Loop ] & 0x0F0000 ) >> 16 ) ;
            Number [ 2 ] = HexChar ( ( Colors [ Loop ] & 0x00F000 ) >> 12 ) ;
            Number [ 3 ] = HexChar ( ( Colors [ Loop ] & 0x000F00 ) >> 8 ) ;
            Number [ 4 ] = HexChar ( ( Colors [ Loop ] & 0x0000F0 ) >> 4 ) ;
            Number [ 5 ] = HexChar ( ( Colors [ Loop ] & 0x00000F ) ) ;
            Number [ 6 ] = 0 ;
            sock_write ( & TCPSocket , Number , strlen ( Number ) ) ;
            sock_write ( & TCPSocket , WebPageSrc7 , strlen ( WebPageSrc7 ) ) ;
          } /* for */ ;
          sock_write ( & TCPSocket , WebPageSrc8 , strlen ( WebPageSrc8 ) ) ;
          break ;
        } /* if */ ;
      } /* if */ ;
      tcp_tick ( & TCPSocket ) ;
     } /* for */ ;
     puts ( "****Rozlaczenie\n" ) ;
     sock_close( & TCPSocket );
  } /* for */ ;
} /* main */
Wygenerowana przykładowa strona wygląda następująco:

Kod: Zaznacz cały

<html>
<head>
<meta http-equiv="refresh" content="5">
<title>RABBIT 2000 - dynamiczne serwowanie strony</title>
</head>
<body bgcolor="#3030A0" text="#FFFF00">
<p><b><font color="#FFFFFF" size="6"><i>Witaj Koles z microgeek.eu przy kompie,<br>sterowanie i pomiary, domowa automatyka</i></font></b></p>
<p><b>System pomiarowy: MEROPE M45</b></p>
<b>Dane pomiarowe: 250</b>
<table bgcolor="#ffffff" border="5" cellpadding="0" cellspacing="0" width="500">
<tr><td><table width="250" border="0" cellpadding="0" cellspacing="0">
<tr><td bgcolor="#ffff00">&nbsp;</td></tr>
</table></td></tr>
</table>
<b>Dane pomiarowe: 250</b>
<table bgcolor="#ffffff" border="5" cellpadding="0" cellspacing="0" width="500">
<tr><td><table width="250" border="0" cellpadding="0" cellspacing="0">
<tr><td bgcolor="#80ffff">&nbsp;</td></tr>
</table></td></tr>
</table>
<b>Dane pomiarowe: 250</b>
<table bgcolor="#ffffff" border="5" cellpadding="0" cellspacing="0" width="500">
<tr><td><table width="250" border="0" cellpadding="0" cellspacing="0">
<tr><td bgcolor="#40bf80">&nbsp;</td></tr>
</table></td></tr>
</table>
<b>Dane pomiarowe: 250</b>
<table bgcolor="#ffffff" border="5" cellpadding="0" cellspacing="0" width="500">
<tr><td><table width="250" border="0" cellpadding="0" cellspacing="0">
<tr><td bgcolor="#0040ff">&nbsp;</td></tr>
</table></td></tr>
</table>
<b>Dane pomiarowe: 250</b>
<table bgcolor="#ffffff" border="5" cellpadding="0" cellspacing="0" width="500">
<tr><td><table width="250" border="0" cellpadding="0" cellspacing="0">
<tr><td bgcolor="#ff0000">&nbsp;</td></tr>
</table></td></tr>
</table>
<b>Dane pomiarowe: 250</b>
<table bgcolor="#ffffff" border="5" cellpadding="0" cellspacing="0" width="500">
<tr><td><table width="250" border="0" cellpadding="0" cellspacing="0">
<tr><td bgcolor="#FFBF00">&nbsp;</td></tr>
</table></td></tr>
</table>
<b>Dane pomiarowe: 250</b>
<table bgcolor="#ffffff" border="5" cellpadding="0" cellspacing="0" width="500">
<tr><td><table width="250" border="0" cellpadding="0" cellspacing="0">
<tr><td bgcolor="#0075ff">&nbsp;</td></tr>
</table></td></tr>
</table>
</body>
</html>
Patrząc na program mam świadomość jego niedoskonałości. Trzeba tu i ówdzie coś poprawić, zoptymalizować, zmodyfikować. Zrealizuję każdy plan jaki przyjdzie mi do głowy i nie ma inaczej. Będzie tak jak powinno być.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

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


Wróć do „Inne mikroklocki, również peryferyjne”

Kto jest online

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