LWPM Comfort Module/Tworzenie akcji: Różnice pomiędzy wersjami

Z LWPM
Przejdź do nawigacji Przejdź do wyszukiwania
 
(Nie pokazano 41 pośrednich wersji utworzonych przez tego samego użytkownika)
Linia 8: Linia 8:
 
Ogólny format akcji przedstawia się następująco:
 
Ogólny format akcji przedstawia się następująco:
  
<code>
+
;:<code><[[#Informacje o akcji|informacje o akcji]]> <[[#Ilość powtórzeń|ilość powtórzeń]]> <[[#Początek akcji|początek akcji]]> <[[#Koniec akcji|koniec akcji]]> <[[#Pętla|pętla]]></code>
<[[#Informacje o akcji|informacje o akcji]]> <[[#Ilość powtórzeń|ilość powtórzeń]]> <[[#Początek akcji|początek akcji]]> <[[#Koniec akcji|koniec akcji]]> <[[#Pętla|pętla]]>
+
 
</code>
+
Z tego wynika, że najprostsza akcja, która nic nie robi wygląda następująco:
 +
: <code>00 00 00 00 00</code>
  
 
=== Informacje o akcji ===
 
=== Informacje o akcji ===
Linia 17: Linia 18:
  
 
==== Format danych ====
 
==== Format danych ====
<code>
+
;:<code><informacje o akcji> = <długość informacji> <informacje>*</code>
<informacje o akcji> = <długość informacji> <informacje>*
 
</code>
 
  
<code><długość informacji></code> określa długość wszystkich informacji w bajtach
+
;<code><długość informacji></code>: określa długość wszystkich informacji w bajtach
  
<code><informacje></code> to szczegółowy opis zachowania akcji. Takich informacji może być kilka dla każdej akcji, przy czym każda musi być innego typu.
+
;<code><informacje></code>: to szczegółowy opis zachowania akcji. Takich informacji może być kilka dla każdej akcji, przy czym każda musi być innego typu.
  
 
Każda informacja jest zapisana w ten sam sposób:
 
Każda informacja jest zapisana w ten sam sposób:
  
<code><informacje> = <typ danych> <długość danych> <dane></code>
+
;:<code><informacje> = <typ informacji> <długość danych> <dane></code>
  
Pierwszym polem jest <code><typ danych></code> (1 bajt) następnie podana jest <code><długość danych></code> w bajtach (1 bajt). Następnie są <code><dane></code>, których format zależy od typu danych.
+
Pierwszym polem jest <code><typ informacji></code> (1 bajt) następnie podana jest <code><długość danych></code> w bajtach (1 bajt) oraz  <code><dane></code>, których format zależy od typu danych.
  
 
==== Informacje o etapach wykonania pętli ====
 
==== Informacje o etapach wykonania pętli ====
<code><typ danych> == 1</code>
+
:<code><typ informacji> == 01</code>
  
 
TODO:
 
TODO:
  
 
==== Informacje o warunkach wykonania akcji ====
 
==== Informacje o warunkach wykonania akcji ====
<code><typ danych> == 2</code>
+
:<code><typ informacji> == 02</code>
  
 
Ten typ informacji określa szczegółowo, jakie muszą zajść warunki by akcja została uruchomiona.
 
Ten typ informacji określa szczegółowo, jakie muszą zajść warunki by akcja została uruchomiona.
 +
 +
===== Format informacji =====
 +
;:<code><dane> = <index> <flagi> <start> <stop> <instrukcja>*</code>
 +
 +
;<code><index></code>: miejsce zapisu o aktualnym stanie akcji.
 +
:Dostępne są 4 takie miejsca (<code>00</code> - <code>03</code>).
 +
:Każda akcja warunkowa powinna być wykonywana we własnym miejscu (każda powinna mieć inną wartość <code><index></code>) aby akcje ze sobą nie interferowały. Oczywiście akcje będą działały na tym samym indeksie, jednak może być trudno zapanować nad poprawności warunków.
 +
:Możliwe jest także wpisanie wartości <code>FF</code> która spowoduje, że wynik obliczeń nie będzie nigdzie zapisywany.
 +
:Wartość (<code>00</code> - <code>03</code>) powinna być użyta dla akcji działających jako akcje w tle, natomiast wartość <code>FF</code> dla pozostałych akcji.
 +
 +
;<code><flagi></code>: flagi zmieniające zachowanie kalkulatora wyliczającego warunek.
 +
:Domyślna wartość to <code>00</code>.
 +
:Dostępne są następujące flagi:
 +
:;<code>01</code>: w przypadku jakiegokolwiek błędu odczytu któregokolwiek parametru pracy modułu, obliczenia zostaną uznane za poprawne - wynik obliczeń będzie prawidłowo, a wiec może dojść do uruchomienia akcji. Domyślnie jakikolwiek błąd w obliczeniach powoduje, że akcja zostanie przerwana lub się nie uruchomi.
 +
 +
;<code><start></code>: określa ilość prawidłowych obliczeń jaka jest wymagana by akcja się uruchomiła. W przypadku gdy wartość jest równa <code>00</code> - akcja wykona się zawsze (wartość ta w zasadzie nie ma większego sensu)
 +
 +
;<code><stop></code>: określa ilość prawidłowych obliczeń jaka jest wymagana by akcja się zakończyła. W przypadku gdy wartość jest równa <code>00</code> - akcja zakończy się zawsze (wartość ta w zasadzie nie ma większego sensu)
 +
 +
;<code><instrukcja>*</code>: ciąg instrukcji dla kalkulatora
 +
 +
===== Zasada działania kalkulatora =====
 +
Obliczenia warunku są wykonywane na zasadzie zbliżonej do kalkulatora działającego na zasadzie RPN (odwrócona polska notacja). Tj: najpierw podajemy argumenty instrukcji, następnie operacje jaką chcemy na tych argumentach wykonać. Wynikiem kalkulatora jest wartość <code>0</code> jeśli warunek jest niespełniony, lub wartość różna od <code>0</code> jeśli warunek jest prawdziwy i kalkulator możesz przejść do uruchomienia akcji (po określonej ilości poprawnych obliczeń).
 +
 +
Kalkulator posiada następujące rejestry:
 +
 +
* <code>a</code> - rejestr 32-bitowy (liczba ze znakiem)
 +
* <code>b</code> - rejestr 32-bitowy (liczba ze znakiem)
 +
* <code>save[x]</code> - 4 elementowa tablica 32-bitowych liczb ze znakiem. Do tymczasowego przechowywania danych. Na tych liczbach nie można wykonywać bezpośrednio operacji - należy je najpierw przenieść do rejestrów <code>a</code> lub <code>b</code>.
 +
 +
===== Dostępne instrukcje =====
 +
W kalkulatorze dostępnych jest szereg instrukcji które są wykorzystywane do wykonywania obliczeń.
 +
W poniższej tabeli jest zestawienie tych instrukcji.
 +
{| class="wikitable"
 +
|-
 +
! Instrukcja
 +
! Operacja
 +
! Opis
 +
|-
 +
! colspan="3"|operacje ładowania stałych wartości (liczb)
 +
|-
 +
|style="white-space: nowrap;"|<code>00</code>
 +
|
 +
<pre>a = b
 +
b = 0</pre>
 +
|
 +
; Load 0: przepisz zawartość rejestru <code>b</code> do rejestru <code>a</code> oraz
 +
:wpisz do rejestru <code>b</code> wartość <code>0</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>01</code>
 +
|
 +
<pre>a = b
 +
b = 1</pre>
 +
|
 +
;Load 1: przepisz zawartość rejestru <code>b</code> do rejestru <code>a</code> oraz
 +
:wpisz do rejestru <code>b</code> wartość <code>1</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>02</code>
 +
|
 +
<pre>a = b
 +
b = -1</pre>
 +
|
 +
;Load -1: przepisz zawartość rejestru <code>b</code> do rejestru <code>a</code> oraz
 +
:wpisz do rejestru <code>b</code> wartość <code>-1</code> (<code>0xFFFFFFFF</code>)
 +
|-
 +
|style="white-space: nowrap;"|<code>03 <xx></code>
 +
|
 +
<pre>a = b
 +
b = <xx> </pre>
 +
|
 +
;LoadSignedByte: przepisz zawartość rejestru <code>b</code> do rejestru <code>a</code> oraz
 +
:wpisz do rejestru <code>b</code> wartość <code><xx></code>, która interpretowana jest jako 8-bitowa liczba ze znakiem
 +
|-
 +
|style="white-space: nowrap;"|<code>04 <xx></code>
 +
|
 +
<pre>a = b
 +
b = <xx> </pre>
 +
|
 +
;LoadUnsignedByte: przepisz zawartość rejestru <code>b</code> do rejestru <code>a</code> oraz
 +
:wpisz do rejestru <code>b</code> wartość <code><xx></code>, która interpretowana jest jako 8-bitowa liczna bez znaku
 +
|-
 +
|style="white-space: nowrap;"|<code>05 <xxxx></code>
 +
|
 +
<pre>a = b
 +
b = <xxxx> </pre>
 +
|
 +
;LoadSignedWord: przepisz zawartość rejestru <code>b</code> do rejestru <code>a</code> oraz
 +
:wpisz do rejestru <code>b</code> wartość <code><xxxx></code>, która interpretowana jest jako 16-bitowa liczba ze znakiem
 +
|-
 +
|style="white-space: nowrap;"|<code>06 <xxxx></code>
 +
|
 +
<pre>a = b
 +
b = <xxxx> </pre>
 +
|
 +
;LoadUnsignedWord: przepisz zawartość rejestru <code>b</code> do rejestru <code>a</code> oraz
 +
:wpisz do rejestru <code>b</code> wartość <code><xxxx></code>, która interpretowana jest jako 16-bitowa liczba bez znaku
 +
|-
 +
|style="white-space: nowrap;"|<code>07 <xxxxxxxx></code>
 +
|
 +
<pre>a = b
 +
b = <xxxxxxxx> </pre>
 +
|
 +
;LoadDoubleWord: przepisz zawartość rejestru <code>b</code> do rejestru <code>a</code> oraz
 +
:wpisz do rejestru <code>b</code> wartość <code><xxxxxxxx></code>, która interpretowana jest jako 32-bitowa liczba ze znakiem
 +
|-
 +
|style="white-space: nowrap;"|<code>10 <nn></code>
 +
|
 +
<pre>save[<nn>] = a</pre>
 +
|
 +
;SaveB: przepisz zawartość rejestru <code>b</code> do rejestru <code>save[n]</code> (rejestr <code>save</code> na pozycji <code>n</code>)
 +
|-
 +
|style="white-space: nowrap;"|<code>11 <nn></code>
 +
|
 +
<pre>save[<nn>] = b</pre>
 +
|
 +
;SaveB: przepisz zawartość rejestru <code>b</code> do rejestru <code>save[n]</code> (rejestr <code>save</code> na pozycji <code>n</code>)
 +
|-
 +
|style="white-space: nowrap;"|<code>14 <nn></code>
 +
|
 +
<pre>a = save[<nn>]</pre>
 +
|
 +
;RestoreA: przepisz zawartość rejestru <code>save[n]</code> (rejestr <code>save</code> na pozycji <code>n</code>) do rejestru <code>a</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>15 <nn></code>
 +
|
 +
<pre>b = save[<nn>]</pre>
 +
|
 +
;RestoreB: przepisz zawartość rejestru <code>save[n]</code> (rejestr <code>save</code> na pozycji <code>n</code>) do rejestru <code>b</code>
 +
|-
 +
! colspan="3"|operacje ładowania parametru pracy silnika (modułu)
 +
|-
 +
|style="white-space: nowrap;"|<code>20 <nn></code>
 +
|
 +
<pre>a = b
 +
b = ReadDiagnosticsValue(<nnnn>)</pre>
 +
|
 +
;ReadDiagnosticsValue: przepisz zawartość rejestru <code>b</code> do rejestru <code>a</code> oraz wpisz do rejestru <code>b</code> jedną z wartości z diagnostyki
 +
 +
Spisz wszystkich dostępnych parametrów na [[LWPM_Comfort_Module/ECUInfo|tej stronie]].
 +
|-
 +
|style="white-space: nowrap;"|<code>23 <lan> <tx> <rx> <sts> <id> <byte></code>
 +
|
 +
<pre>a = b
 +
b = ReadModuleStatus(<id>)</pre>
 +
|
 +
;ReadModuleStatus: przepisz zawartość rejestru <code>b</code> do rejestru <code>a</code> oraz
 +
:wpisz do rejestru <code>b</code> wybrane 4 bajty z rejestru statusu modułu do <code>b</code>
 +
Parametry:
 +
{| class="wikitable"
 +
! parametr
 +
! znaczenie
 +
|-
 +
|style="white-space: nowrap;"|<code><lan></code>
 +
|
 +
;szyna CAN na której znajduje się moduł
 +
:<code>00</code> - LSCAN
 +
:<code>01</code> - MSCAN
 +
:<code>02</code> - HSCAN
 +
:<code>03</code> - CHCAN
 +
 +
|-
 +
|style="white-space: nowrap;"|<code><tx></code>
 +
|
 +
;adres na którym moduł nasłuchuje na CAN
 +
:<code><xxxx></code>, np dla sterownika silnika: <code>07E0</code>
 +
|-
 +
|style="white-space: nowrap;"|<code><rs></code>
 +
|
 +
;adres na którym moduł odpowiada na CAN
 +
:<code><xxxx></code>, np dla sterownika silnika: <code>07E8</code>
 +
|-
 +
|style="white-space: nowrap;"|<code><srs></code>
 +
|
 +
;adres na którym moduł wysyła statusy na CAN
 +
:<code><xxxx></code>, np dla sterownika silnika: <code>05E8</code>
 +
|-
 +
|style="white-space: nowrap;"|<code><id></code>
 +
|
 +
;identyfikator statusu do odczytania
 +
:<code><xx></code>, np <code>03</code>
 +
|-
 +
|style="white-space: nowrap;"|<code><byte></code>
 +
|
 +
;bajt od którego zostanie wczytana wartość
 +
:<code><xx></code>, np dla odczytanego statusu <code>01 02 03 04 05 06 07</code> wartość <code>02</code> spowoduje wpisanie do <code>a</code> wartości <code>0x03040506</code>. Korzystając z pozostałych instrukcji można dotrzeć do dowolnego bajtu/bitu ze statusu.
 +
|}
 +
|-
 +
|style="white-space: nowrap;"|<code>24</code>
 +
|
 +
<pre>a = b
 +
b = ReadIOStatus()</pre>
 +
|
 +
;ReadIOStatus: przepisz zawartość rejestru <code>b</code> do rejestru <code>a</code> oraz
 +
:wpisz do rejestru <code>b</code> stan wszystkich wyjść/wejść modułu (np AUX)
 +
Wartości poszczególnych pinów IO są zapisane w następujący sposób (jedna wartość na każdym bicie rejestru <code>b</code>):
 +
{| class="wikitable"
 +
! bit
 +
! wartość
 +
! IO
 +
|-
 +
| <code>0</code>
 +
| <code>0x01</code>
 +
| C2D
 +
|-
 +
| <code>1</code>
 +
| <code>0x02</code>
 +
| LED-
 +
|-
 +
| <code>2</code>
 +
| <code>0x04</code>
 +
| UART TX
 +
|-
 +
| <code>3</code>
 +
| <code>0x08</code>
 +
| UART_RX
 +
|-
 +
| <code>4</code>
 +
| <code>0x10</code>
 +
| AUX1
 +
|-
 +
| <code>5</code>
 +
| <code>0x20</code>
 +
| AUX2
 +
|-
 +
| <code>6</code>
 +
| <code>0x40</code>
 +
| AUX3
 +
|}
 +
Lokalizacja poszczególnych pinów jest przedstawiona na [[LWPM_Comfort_Module/PCB|tej stronie]].
 +
|-
 +
! colspan="3"|operacje konwersji danych
 +
|-
 +
|style="white-space: nowrap;"|<code>30</code>
 +
|
 +
<pre>b = SignExtend8(b)</pre>
 +
|
 +
;ExtendSignedByte: rozszerz zawartość rejestru <code>b</code> z 8-bitowej liczby ze znakiem do 32-bitowej liczby ze znakiem
 +
|-
 +
|style="white-space: nowrap;"|<code>31</code>
 +
|
 +
<pre>b = ZeroExtend8(b)</pre>
 +
|
 +
;ExtendUnsignedByte: rozszerz zawartość rejestru <code>b</code> z 8-bitowej liczby bez znaku do 32-bitowej liczby ze znakiem
 +
|-
 +
|style="white-space: nowrap;"|<code>32</code>
 +
|
 +
<pre>b = SignExtend16(b)</pre>
 +
|
 +
;ExtendSignedWord: rozszerz zawartość rejestru <code>b</code> z 16-bitowej liczby ze znakiem do 32-bitowej liczby ze znakiem
 +
|-
 +
|style="white-space: nowrap;"|<code>33</code>
 +
|
 +
<pre>b = ZeroExtend16(b)</pre>
 +
|
 +
;ExtendSignedWord: rozszerz zawartość rejestru <code>b</code> z 16-bitowej liczby bez znaku do 32-bitowej liczby ze znakiem
 +
|-
 +
|style="white-space: nowrap;"|<code>34</code>
 +
|
 +
<pre>b = SignExtend1(b)</pre>
 +
|
 +
;ExtendBit: rozszerz zawartość rejestru <code>b</code> z 1-bitowej liczby ze znakiem do 32-bitowej liczby ze znakiem
 +
|-
 +
! colspan="3"|operacje arytmetyczne
 +
|-
 +
|style="white-space: nowrap;"|<code>40</code>
 +
|
 +
<pre><tmp> = a
 +
a = b
 +
b = <tmp></pre>
 +
|
 +
;Exchange: zamień miejscami zawartość rejestru <code>a</code> z rejestrem <code>b</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>41</code>
 +
|
 +
<pre>b = b + a</pre>
 +
|
 +
;Add: Dodaj do rejestru <code>b</code> wartość rejestru <code>a</code> i zapisz wynik w rejestrze <code>b</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>42</code>
 +
|
 +
<pre>b = b - a</pre>
 +
|
 +
;Subtract: Odejmij od rejestru <code>b</code> wartość rejestru <code>a</code> i zapisz wynik w rejestrze <code>b</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>43</code>
 +
|
 +
<pre>b = b * a</pre>
 +
|
 +
;Multiply: Pomnóż wartość z rejestru <code>b</code> i wartość rejestru <code>a</code> i zapisz wynik w rejestrze <code>b</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>44</code>
 +
|
 +
<pre>b = b / a</pre>
 +
|
 +
;Divide: Podziel wartość z rejestru <code>b</code> przez wartość rejestru <code>a</code> i zapisz wynik w rejestrze <code>b</code> (część całkowita wyniku dzielenia)
 +
|-
 +
|style="white-space: nowrap;"|<code>45</code>
 +
|
 +
<pre>b = b % a</pre>
 +
|
 +
;Modulo: Podziel wartość z rejestru <code>b</code> przez wartość rejestru <code>a</code> i zapisz wynik w rejestrze <code>b</code> (reszta z wyniku dzielenia)
 +
|-
 +
|style="white-space: nowrap;"|<code>46</code>
 +
|
 +
<pre>b = -b</pre>
 +
|
 +
;Negate: zmień znak liczby w rejestrze <code>b</code> na przeciwny
 +
|-
 +
|style="white-space: nowrap;"|<code>47</code>
 +
|
 +
<pre>b = b << a</pre>
 +
|
 +
;ShiftLeft: przesuń wartość bitową w rejestrze <code>b</code> w lewo o ilość bitów określoną w rejestrze <code>a</code> i zapisz wynik w rejestrze <code>b</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>48</code>
 +
|
 +
<pre>b = b >> a</pre>
 +
|
 +
;ShiftRight: przesuń wartość bitową w rejestrze <code>b</code> w prawo o ilość bitów określoną w rejestrze <code>a</code> i zapisz wynik w rejestrze <code>b</code>
 +
|-
 +
! colspan="3"|operacje bitowe
 +
|-
 +
|style="white-space: nowrap;"|<code>50</code>
 +
|
 +
<pre>b = b & a</pre>
 +
|
 +
;ArithmeticalAnd: wykonaj bitową operację <code>AND</code> na rejestrach <code>a</code> oraz <code>b</code> i zapisz wynik w rejestrze <code>b</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>51</code>
 +
|
 +
<pre>b = b | a</pre>
 +
|
 +
;ArithmeticalOr: wykonaj bitową operację <code>OR</code> na rejestrach <code>a</code> oraz <code>b</code> i zapisz wynik w rejestrze <code>b</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>52</code>
 +
|
 +
<pre>b = b ^ a</pre>
 +
|
 +
;ArithmeticalXor: wykonaj bitową operację <code>XOR</code> na rejestrach <code>a</code> oraz <code>b</code> i zapisz wynik w rejestrze <code>b</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>53</code>
 +
|
 +
<pre>b = ~b</pre>
 +
|
 +
;ArithmeticalNot: wykonaj bitową operację <code>NOT</code> na rejestrze <code>b</code> i zapisz wynik w rejestrze <code>b</code>
 +
|-
 +
! colspan="3"|operacje logiczne
 +
|-
 +
|style="white-space: nowrap;"|<code>60</code>
 +
|
 +
<pre>if a <> 0 and b <> 0:
 +
    b = 1
 +
else:
 +
    b = 0</pre>
 +
|
 +
;LogicalAnd: wpisuje do rejestru <code>b</code> wartość <code>1</code> wtedy i tylko wtedy gdy wartości w rejestrach <code>a</code> oraz <code>b</code> są różne od <code>0</code>. W przeciwnym przypadku wpisuje wartość <code>0</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>61</code>
 +
|
 +
<pre>if a <> 0 or b <> 0:
 +
    b = 1
 +
else:
 +
    b = 0</pre>
 +
|
 +
;LogicalOr: wpisuje do rejestru <code>b</code> wartość <code>1</code> wtedy i tylko wtedy gdy przynajmniej jedna z wartości w rejestrach <code>a</code> oraz <code>b</code> jest różna od <code>0</code>. W przeciwnym przypadku wpisuje <code>0</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>62</code>
 +
|
 +
<pre>if a <> 0 xor b <> 0:
 +
    b = 1
 +
else:
 +
    b = 0</pre>
 +
|
 +
;LogicalXor: wpisuje do rejestru <code>b</code> wartość <code>1</code> wtedy i tylko wtedy gdy dokładnie jedna z wartości w rejestrach <code>a</code> oraz <code>b</code> jest różna od <code>0</code>. W przeciwnym przypadku wpisuje <code>0</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>63</code>
 +
|
 +
<pre>if b <> 0:
 +
    b = 1
 +
else:
 +
    b = 0</pre>
 +
|
 +
;LogicalNot: wpisuje do rejestru <code>b</code> wartość <code>1</code> wtedy i tylko wtedy gdy zawartość rejestru <code>b</code> jest różna od <code>0</code>. W przeciwnym przypadku wpisuje <code>0</code>
 +
|-
 +
! colspan="3"|instrukcje porównujące dane
 +
|-
 +
|style="white-space: nowrap;"|<code>F0</code>
 +
|
 +
<pre>if b == 0:
 +
    b = 1
 +
else:
 +
    b = 0</pre>
 +
|
 +
;CompareZero: wpisuje do rejestru <code>b</code> wartość <code>1</code> wtedy i tylko wtedy gdy wartość w rejestrze <code>b</code> jest równa <code>0</code>. W przeciwnym przypadku wpisuje wartość <code>0</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>F1</code>
 +
|
 +
<pre>if b <> 0:
 +
    b = 1
 +
else:
 +
    b = 0</pre>
 +
|
 +
;CompareNotZero: wpisuje do rejestru <code>b</code> wartość <code>1</code> wtedy i tylko wtedy gdy wartość w rejestrze <code>b</code> jest różna od <code>0</code>. W przeciwnym przypadku wpisuje wartość <code>0</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>F2</code>
 +
|
 +
<pre>if b < 0:
 +
    b = 1
 +
else:
 +
    b = 0</pre>
 +
|
 +
;CompareLessThanZero: wpisuje do rejestru <code>b</code> wartość <code>1</code> wtedy i tylko wtedy gdy wartość w rejestrze <code>b</code> jest mniejsza od <code>0</code>. W przeciwnym przypadku wpisuje wartość <code>0</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>F3</code>
 +
|
 +
<pre>if b <= 0:
 +
    b = 1
 +
else:
 +
    b = 0</pre>
 +
|
 +
;CompareLessThanOrEqualZero: wpisuje do rejestru <code>b</code> wartość <code>1</code> wtedy i tylko wtedy gdy wartość w rejestrze <code>b</code> jest mniejsza lub równa <code>0</code>. W przeciwnym przypadku wpisuje wartość <code>0</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>F4</code>
 +
|
 +
<pre>if b > 0:
 +
    b = 1
 +
else:
 +
    b = 0</pre>
 +
|
 +
;CompareGreaterThanZero: wpisuje do rejestru <code>b</code> wartość <code>1</code> wtedy i tylko wtedy gdy wartość w rejestrze <code>b</code> jest większa od <code>0</code>. W przeciwnym przypadku wpisuje wartość <code>0</code>
 +
|-
 +
|style="white-space: nowrap;"|<code>F5</code>
 +
|
 +
<pre>if b >= 0:
 +
    b = 1
 +
else:
 +
    b = 0</pre>
 +
|
 +
;CompareGreaterThanOrEqualZero: wpisuje do rejestru <code>b</code> wartość <code>1</code> wtedy i tylko wtedy gdy wartość w rejestrze <code>b</code> jest większa lub równa <code>0</code>. W przeciwnym przypadku wpisuje wartość <code>0</code>
 +
|-
 +
! colspan="3"|koniec obliczeń
 +
|-
 +
|style="white-space: nowrap;"|<code>FD</code>
 +
|
 +
<pre>if b <> 0:
 +
    return 1</pre>
 +
|
 +
;ReturnIfNotZero: zwraca <code>1</code>, jeśli zawartość rejestru <code>b</code> jest różna <code>0</code>. Operacja ta pozwoli na rezygnację z dalszych obliczeń, jeśli już teraz wiadomo, że cały warunek będzie spełniony
 +
|-
 +
|style="white-space: nowrap;"|<code>FE</code>
 +
|
 +
<pre>if b == 0:
 +
    return 0</pre>
 +
|
 +
;ReturnIfZero: zwraca <code>0</code>, jeśli zawartość rejestru <code>b</code> wynosi <code>0</code>. Operacja ta pozwoli na rezygnację z dalszych obliczeń, jeśli już teraz wiadomo, że cały warunek nie będzie spełniony
 +
|-
 +
|style="white-space: nowrap;"|<code>FF</code>
 +
|
 +
<pre>return b</pre>
 +
|
 +
;Return: zwraca w wyniku zawartość rejestru <code>b</code>. Gdy wartość ta jest różna od <code>0</code>, warunek uznaje się za spełniony
 +
|}
  
 
=== Ilość powtórzeń ===
 
=== Ilość powtórzeń ===
Linia 48: Linia 509:
  
 
=== Pętla ===
 
=== Pętla ===
 +
 +
== Dostępne polecenia ==

Aktualna wersja na dzień 11:32, 15 sty 2024

Moduł daje możliwość wykonania dowolnej akcji.

W tym miejscu opisany jest format akcji oraz możliwości i polecenia jakie mogą być zawarte w akcji.

Wszystkie liczby i wartości są podane w formacie szesnastkowym (HEX).

Format akcji

Ogólny format akcji przedstawia się następująco:

<informacje o akcji> <ilość powtórzeń> <początek akcji> <koniec akcji> <pętla>

Z tego wynika, że najprostsza akcja, która nic nie robi wygląda następująco:

00 00 00 00 00

Informacje o akcji

Informacje o akcji zawierają bardziej szczegółowe informacje na temat akcji opisujące przede wszystkim sposób wykonania akcji. Przykładowo można tutaj określić szczegółowo warunki uruchomienia akcji, a także w tym miejscu możesz zdefiniować jak mają wykonywać się poszczególne etapy pętli.

Format danych

<informacje o akcji> = <długość informacji> <informacje>*
<długość informacji>
określa długość wszystkich informacji w bajtach
<informacje>
to szczegółowy opis zachowania akcji. Takich informacji może być kilka dla każdej akcji, przy czym każda musi być innego typu.

Każda informacja jest zapisana w ten sam sposób:

<informacje> = <typ informacji> <długość danych> <dane>

Pierwszym polem jest <typ informacji> (1 bajt) następnie podana jest <długość danych> w bajtach (1 bajt) oraz <dane>, których format zależy od typu danych.

Informacje o etapach wykonania pętli

<typ informacji> == 01

TODO:

Informacje o warunkach wykonania akcji

<typ informacji> == 02

Ten typ informacji określa szczegółowo, jakie muszą zajść warunki by akcja została uruchomiona.

Format informacji
<dane> = <index> <flagi> <start> <stop> <instrukcja>*
<index>
miejsce zapisu o aktualnym stanie akcji.
Dostępne są 4 takie miejsca (00 - 03).
Każda akcja warunkowa powinna być wykonywana we własnym miejscu (każda powinna mieć inną wartość <index>) aby akcje ze sobą nie interferowały. Oczywiście akcje będą działały na tym samym indeksie, jednak może być trudno zapanować nad poprawności warunków.
Możliwe jest także wpisanie wartości FF która spowoduje, że wynik obliczeń nie będzie nigdzie zapisywany.
Wartość (00 - 03) powinna być użyta dla akcji działających jako akcje w tle, natomiast wartość FF dla pozostałych akcji.
<flagi>
flagi zmieniające zachowanie kalkulatora wyliczającego warunek.
Domyślna wartość to 00.
Dostępne są następujące flagi:
01
w przypadku jakiegokolwiek błędu odczytu któregokolwiek parametru pracy modułu, obliczenia zostaną uznane za poprawne - wynik obliczeń będzie prawidłowo, a wiec może dojść do uruchomienia akcji. Domyślnie jakikolwiek błąd w obliczeniach powoduje, że akcja zostanie przerwana lub się nie uruchomi.
<start>
określa ilość prawidłowych obliczeń jaka jest wymagana by akcja się uruchomiła. W przypadku gdy wartość jest równa 00 - akcja wykona się zawsze (wartość ta w zasadzie nie ma większego sensu)
<stop>
określa ilość prawidłowych obliczeń jaka jest wymagana by akcja się zakończyła. W przypadku gdy wartość jest równa 00 - akcja zakończy się zawsze (wartość ta w zasadzie nie ma większego sensu)
<instrukcja>*
ciąg instrukcji dla kalkulatora
Zasada działania kalkulatora

Obliczenia warunku są wykonywane na zasadzie zbliżonej do kalkulatora działającego na zasadzie RPN (odwrócona polska notacja). Tj: najpierw podajemy argumenty instrukcji, następnie operacje jaką chcemy na tych argumentach wykonać. Wynikiem kalkulatora jest wartość 0 jeśli warunek jest niespełniony, lub wartość różna od 0 jeśli warunek jest prawdziwy i kalkulator możesz przejść do uruchomienia akcji (po określonej ilości poprawnych obliczeń).

Kalkulator posiada następujące rejestry:

  • a - rejestr 32-bitowy (liczba ze znakiem)
  • b - rejestr 32-bitowy (liczba ze znakiem)
  • save[x] - 4 elementowa tablica 32-bitowych liczb ze znakiem. Do tymczasowego przechowywania danych. Na tych liczbach nie można wykonywać bezpośrednio operacji - należy je najpierw przenieść do rejestrów a lub b.
Dostępne instrukcje

W kalkulatorze dostępnych jest szereg instrukcji które są wykorzystywane do wykonywania obliczeń. W poniższej tabeli jest zestawienie tych instrukcji.

Instrukcja Operacja Opis
operacje ładowania stałych wartości (liczb)
00
a = b
b = 0
Load 0
przepisz zawartość rejestru b do rejestru a oraz
wpisz do rejestru b wartość 0
01
a = b
b = 1
Load 1
przepisz zawartość rejestru b do rejestru a oraz
wpisz do rejestru b wartość 1
02
a = b
b = -1
Load -1
przepisz zawartość rejestru b do rejestru a oraz
wpisz do rejestru b wartość -1 (0xFFFFFFFF)
03 <xx>
a = b
b = <xx> 
LoadSignedByte
przepisz zawartość rejestru b do rejestru a oraz
wpisz do rejestru b wartość <xx>, która interpretowana jest jako 8-bitowa liczba ze znakiem
04 <xx>
a = b
b = <xx> 
LoadUnsignedByte
przepisz zawartość rejestru b do rejestru a oraz
wpisz do rejestru b wartość <xx>, która interpretowana jest jako 8-bitowa liczna bez znaku
05 <xxxx>
a = b
b = <xxxx> 
LoadSignedWord
przepisz zawartość rejestru b do rejestru a oraz
wpisz do rejestru b wartość <xxxx>, która interpretowana jest jako 16-bitowa liczba ze znakiem
06 <xxxx>
a = b
b = <xxxx> 
LoadUnsignedWord
przepisz zawartość rejestru b do rejestru a oraz
wpisz do rejestru b wartość <xxxx>, która interpretowana jest jako 16-bitowa liczba bez znaku
07 <xxxxxxxx>
a = b
b = <xxxxxxxx> 
LoadDoubleWord
przepisz zawartość rejestru b do rejestru a oraz
wpisz do rejestru b wartość <xxxxxxxx>, która interpretowana jest jako 32-bitowa liczba ze znakiem
10 <nn>
save[<nn>] = a
SaveB
przepisz zawartość rejestru b do rejestru save[n] (rejestr save na pozycji n)
11 <nn>
save[<nn>] = b
SaveB
przepisz zawartość rejestru b do rejestru save[n] (rejestr save na pozycji n)
14 <nn>
a = save[<nn>]
RestoreA
przepisz zawartość rejestru save[n] (rejestr save na pozycji n) do rejestru a
15 <nn>
b = save[<nn>]
RestoreB
przepisz zawartość rejestru save[n] (rejestr save na pozycji n) do rejestru b
operacje ładowania parametru pracy silnika (modułu)
20 <nn>
a = b
b = ReadDiagnosticsValue(<nnnn>)
ReadDiagnosticsValue
przepisz zawartość rejestru b do rejestru a oraz wpisz do rejestru b jedną z wartości z diagnostyki

Spisz wszystkich dostępnych parametrów na tej stronie.

23 <lan> <tx> <rx> <sts> <id> <byte>
a = b
b = ReadModuleStatus(<id>)
ReadModuleStatus
przepisz zawartość rejestru b do rejestru a oraz
wpisz do rejestru b wybrane 4 bajty z rejestru statusu modułu do b

Parametry:

parametr znaczenie
<lan>
szyna CAN na której znajduje się moduł
00 - LSCAN
01 - MSCAN
02 - HSCAN
03 - CHCAN
<tx>
adres na którym moduł nasłuchuje na CAN
<xxxx>, np dla sterownika silnika: 07E0
<rs>
adres na którym moduł odpowiada na CAN
<xxxx>, np dla sterownika silnika: 07E8
<srs>
adres na którym moduł wysyła statusy na CAN
<xxxx>, np dla sterownika silnika: 05E8
<id>
identyfikator statusu do odczytania
<xx>, np 03
<byte>
bajt od którego zostanie wczytana wartość
<xx>, np dla odczytanego statusu 01 02 03 04 05 06 07 wartość 02 spowoduje wpisanie do a wartości 0x03040506. Korzystając z pozostałych instrukcji można dotrzeć do dowolnego bajtu/bitu ze statusu.
24
a = b
b = ReadIOStatus()
ReadIOStatus
przepisz zawartość rejestru b do rejestru a oraz
wpisz do rejestru b stan wszystkich wyjść/wejść modułu (np AUX)

Wartości poszczególnych pinów IO są zapisane w następujący sposób (jedna wartość na każdym bicie rejestru b):

bit wartość IO
0 0x01 C2D
1 0x02 LED-
2 0x04 UART TX
3 0x08 UART_RX
4 0x10 AUX1
5 0x20 AUX2
6 0x40 AUX3

Lokalizacja poszczególnych pinów jest przedstawiona na tej stronie.

operacje konwersji danych
30
b = SignExtend8(b)
ExtendSignedByte
rozszerz zawartość rejestru b z 8-bitowej liczby ze znakiem do 32-bitowej liczby ze znakiem
31
b = ZeroExtend8(b)
ExtendUnsignedByte
rozszerz zawartość rejestru b z 8-bitowej liczby bez znaku do 32-bitowej liczby ze znakiem
32
b = SignExtend16(b)
ExtendSignedWord
rozszerz zawartość rejestru b z 16-bitowej liczby ze znakiem do 32-bitowej liczby ze znakiem
33
b = ZeroExtend16(b)
ExtendSignedWord
rozszerz zawartość rejestru b z 16-bitowej liczby bez znaku do 32-bitowej liczby ze znakiem
34
b = SignExtend1(b)
ExtendBit
rozszerz zawartość rejestru b z 1-bitowej liczby ze znakiem do 32-bitowej liczby ze znakiem
operacje arytmetyczne
40
<tmp> = a
a = b
b = <tmp>
Exchange
zamień miejscami zawartość rejestru a z rejestrem b
41
b = b + a
Add
Dodaj do rejestru b wartość rejestru a i zapisz wynik w rejestrze b
42
b = b - a
Subtract
Odejmij od rejestru b wartość rejestru a i zapisz wynik w rejestrze b
43
b = b * a
Multiply
Pomnóż wartość z rejestru b i wartość rejestru a i zapisz wynik w rejestrze b
44
b = b / a
Divide
Podziel wartość z rejestru b przez wartość rejestru a i zapisz wynik w rejestrze b (część całkowita wyniku dzielenia)
45
b = b % a
Modulo
Podziel wartość z rejestru b przez wartość rejestru a i zapisz wynik w rejestrze b (reszta z wyniku dzielenia)
46
b = -b
Negate
zmień znak liczby w rejestrze b na przeciwny
47
b = b << a
ShiftLeft
przesuń wartość bitową w rejestrze b w lewo o ilość bitów określoną w rejestrze a i zapisz wynik w rejestrze b
48
b = b >> a
ShiftRight
przesuń wartość bitową w rejestrze b w prawo o ilość bitów określoną w rejestrze a i zapisz wynik w rejestrze b
operacje bitowe
50
b = b & a
ArithmeticalAnd
wykonaj bitową operację AND na rejestrach a oraz b i zapisz wynik w rejestrze b
51
b = b | a
ArithmeticalOr
wykonaj bitową operację OR na rejestrach a oraz b i zapisz wynik w rejestrze b
52
b = b ^ a
ArithmeticalXor
wykonaj bitową operację XOR na rejestrach a oraz b i zapisz wynik w rejestrze b
53
b = ~b
ArithmeticalNot
wykonaj bitową operację NOT na rejestrze b i zapisz wynik w rejestrze b
operacje logiczne
60
if a <> 0 and b <> 0:
    b = 1
else:
    b = 0
LogicalAnd
wpisuje do rejestru b wartość 1 wtedy i tylko wtedy gdy wartości w rejestrach a oraz b są różne od 0. W przeciwnym przypadku wpisuje wartość 0
61
if a <> 0 or b <> 0:
    b = 1
else:
    b = 0
LogicalOr
wpisuje do rejestru b wartość 1 wtedy i tylko wtedy gdy przynajmniej jedna z wartości w rejestrach a oraz b jest różna od 0. W przeciwnym przypadku wpisuje 0
62
if a <> 0 xor b <> 0:
    b = 1
else:
    b = 0
LogicalXor
wpisuje do rejestru b wartość 1 wtedy i tylko wtedy gdy dokładnie jedna z wartości w rejestrach a oraz b jest różna od 0. W przeciwnym przypadku wpisuje 0
63
if b <> 0:
    b = 1
else:
    b = 0
LogicalNot
wpisuje do rejestru b wartość 1 wtedy i tylko wtedy gdy zawartość rejestru b jest różna od 0. W przeciwnym przypadku wpisuje 0
instrukcje porównujące dane
F0
if b == 0:
    b = 1
else:
    b = 0
CompareZero
wpisuje do rejestru b wartość 1 wtedy i tylko wtedy gdy wartość w rejestrze b jest równa 0. W przeciwnym przypadku wpisuje wartość 0
F1
if b <> 0:
    b = 1
else:
    b = 0
CompareNotZero
wpisuje do rejestru b wartość 1 wtedy i tylko wtedy gdy wartość w rejestrze b jest różna od 0. W przeciwnym przypadku wpisuje wartość 0
F2
if b < 0:
    b = 1
else:
    b = 0
CompareLessThanZero
wpisuje do rejestru b wartość 1 wtedy i tylko wtedy gdy wartość w rejestrze b jest mniejsza od 0. W przeciwnym przypadku wpisuje wartość 0
F3
if b <= 0:
    b = 1
else:
    b = 0
CompareLessThanOrEqualZero
wpisuje do rejestru b wartość 1 wtedy i tylko wtedy gdy wartość w rejestrze b jest mniejsza lub równa 0. W przeciwnym przypadku wpisuje wartość 0
F4
if b > 0:
    b = 1
else:
    b = 0
CompareGreaterThanZero
wpisuje do rejestru b wartość 1 wtedy i tylko wtedy gdy wartość w rejestrze b jest większa od 0. W przeciwnym przypadku wpisuje wartość 0
F5
if b >= 0:
    b = 1
else:
    b = 0
CompareGreaterThanOrEqualZero
wpisuje do rejestru b wartość 1 wtedy i tylko wtedy gdy wartość w rejestrze b jest większa lub równa 0. W przeciwnym przypadku wpisuje wartość 0
koniec obliczeń
FD
if b <> 0:
    return 1
ReturnIfNotZero
zwraca 1, jeśli zawartość rejestru b jest różna 0. Operacja ta pozwoli na rezygnację z dalszych obliczeń, jeśli już teraz wiadomo, że cały warunek będzie spełniony
FE
if b == 0:
    return 0
ReturnIfZero
zwraca 0, jeśli zawartość rejestru b wynosi 0. Operacja ta pozwoli na rezygnację z dalszych obliczeń, jeśli już teraz wiadomo, że cały warunek nie będzie spełniony
FF
return b
Return
zwraca w wyniku zawartość rejestru b. Gdy wartość ta jest różna od 0, warunek uznaje się za spełniony

Ilość powtórzeń

Początek akcji

Koniec akcji

Pętla

Dostępne polecenia