ringbuffer.awl 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. FUNCTION_BLOCK "Ringpuffer"
  2. TITLE =Ringpuffer (FIFO) mit 32-bit breiten Elementen
  3. VERSION : 0.1
  4. VAR_INPUT
  5. eingabe : BOOL ;
  6. ausgabe : BOOL ;
  7. eingabe_wert : DWORD ;
  8. reset : BOOL ;
  9. END_VAR
  10. VAR_OUTPUT
  11. ausgabe_wert : DWORD ;
  12. ueberlauf : BOOL ;
  13. unterlauf : BOOL ;
  14. fuellstand : INT ;
  15. END_VAR
  16. VAR
  17. fm_eingabe : BOOL ;
  18. fm_ausgabe : BOOL ;
  19. anzahl_belegt : INT ;
  20. ptr_eingabe : DWORD ;
  21. ptr_ausgabe : DWORD ;
  22. elemente : ARRAY [0 .. 31 ] OF DWORD ;
  23. END_VAR
  24. VAR_TEMP
  25. max_anzahl_elemente : INT ;
  26. zaehler : INT ;
  27. END_VAR
  28. BEGIN
  29. NETWORK
  30. TITLE =Konstanten definieren
  31. L 32; // Groesse des "elemente" Arrays
  32. T #max_anzahl_elemente;
  33. NETWORK
  34. TITLE =Ringpuffer entladen
  35. U #ausgabe; // "ausgabe" positive Flanke?
  36. FP #fm_ausgabe;
  37. SPBN end1; // Nein? Dann Ende.
  38. L #anzahl_belegt;
  39. L 0;
  40. ==D ; // anzahl_belegt == 0?
  41. SPBN nunt; // ... dann kein Unterlauf
  42. SET ;
  43. = #unterlauf; // ... sonst Unterlauf anzeigen
  44. L 0;
  45. T #ausgabe_wert;
  46. SPA end1; // Und Ende.
  47. nunt: L P##elemente;
  48. L #ptr_ausgabe;
  49. +D ; // AR1 = element_0 + ptr_ausgabe
  50. LAR1 ; // AR1 zeigt auf das erste belegte Element
  51. L D [AR1,P#0.0];
  52. T #ausgabe_wert; // ausgabe_wert = erstes belegtes Element
  53. L 0; // Element nullen. (Nicht unbedingt noetig)
  54. T D [AR1,P#0.0];
  55. L #anzahl_belegt;
  56. L 1;
  57. -D ; // anzahl_belegt -= 1
  58. T #anzahl_belegt;
  59. L #ptr_ausgabe;
  60. L P#4.0;
  61. +D ; // ptr_ausgabe += 4
  62. T #ptr_ausgabe;
  63. L #max_anzahl_elemente;
  64. L P#4.0;
  65. *D ; // akku = Pointer auf Ringende
  66. L #ptr_ausgabe;
  67. >D ; // ptr_ausgabe < Ringende
  68. SPB end0; // ... dann Ende
  69. L P#0.0; // ... sonst ptr_ausgabe = P#0.0
  70. T #ptr_ausgabe;
  71. end0: CLR ;
  72. = #ueberlauf; // Fehleranzeigen zuruecksetzen
  73. = #unterlauf;
  74. end1: NOP 0;
  75. NETWORK
  76. TITLE =Ringpuffer beladen
  77. U #eingabe; // "eingabe" positive Flanke?
  78. FP #fm_eingabe;
  79. SPBN end3; // Nein? Dann Ende.
  80. L #anzahl_belegt;
  81. L #max_anzahl_elemente;
  82. <D ; // anzahl_belegt < max_anzahl?
  83. SPB nueb; // ... dann kein Ueberlauf
  84. SET ;
  85. = #ueberlauf; // ... sonst Ueberlauf anzeigen
  86. SPA end3; // Und Ende.
  87. nueb: L P##elemente;
  88. L #ptr_eingabe;
  89. +D ; // AR1 = element_0 + ptr_eingabe
  90. LAR1 ; // AR1 zeigt auf das erste freie Element
  91. L #eingabe_wert;
  92. T D [AR1,P#0.0]; // Erstes freies Element = eingabe_wert
  93. L #anzahl_belegt;
  94. L 1;
  95. +D ; // anzahl_belegt += 1
  96. T #anzahl_belegt;
  97. L #ptr_eingabe;
  98. L P#4.0;
  99. +D ; // ptr_eingabe += 4
  100. T #ptr_eingabe;
  101. L #max_anzahl_elemente;
  102. L P#4.0;
  103. *D ; // akku = Pointer auf Ringende
  104. L #ptr_eingabe;
  105. >D ; // ptr_eingabe < Ringende
  106. SPB end2; // ... dann Ende
  107. L P#0.0; // ... sonst ptr_eingabe = P#0.0
  108. T #ptr_eingabe;
  109. end2: CLR ;
  110. = #ueberlauf; // Fehleranzeigen zuruecksetzen
  111. = #unterlauf;
  112. end3: NOP 0;
  113. NETWORK
  114. TITLE =Reset-Signal verarbeiten
  115. U #reset;
  116. SPBN nrst;
  117. // Statische Variablen und Ausgaenge nullen
  118. L 0;
  119. T #ausgabe_wert;
  120. T #fuellstand;
  121. T #anzahl_belegt;
  122. T #ptr_eingabe;
  123. T #ptr_ausgabe;
  124. CLR ;
  125. = #ueberlauf;
  126. = #unterlauf;
  127. // Alle Elemente nullen.
  128. // Dies ist nicht unbedingt notwendig, aber zur Fehlersuche sinnvoll.
  129. L #max_anzahl_elemente;
  130. next: T #zaehler;
  131. L 1;
  132. -D ;
  133. L P#4.0;
  134. *D ;
  135. L P##elemente;
  136. +D ;
  137. LAR1 ;
  138. L 0;
  139. T D [AR1,P#0.0];
  140. L #zaehler;
  141. LOOP next;
  142. nrst: NOP 0;
  143. NETWORK
  144. TITLE =Fuellstand ausgeben
  145. L #anzahl_belegt;
  146. T #fuellstand;
  147. END_FUNCTION_BLOCK
  148. DATA_BLOCK "DB_Ringpuffer"
  149. "Ringpuffer"
  150. BEGIN
  151. END_DATA_BLOCK
  152. ORGANIZATION_BLOCK OB 1
  153. VAR_TEMP
  154. OB1_EV_CLASS : BYTE; // Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)
  155. OB1_SCAN_1 : BYTE; // 1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)
  156. OB1_PRIORITY : BYTE; // Priority of OB execution
  157. OB1_OB_NUMBR : BYTE; // 1 (Organization block 1, OB 1)
  158. OB1_RESERVED_1 : BYTE;
  159. OB1_RESERVED_2 : BYTE;
  160. OB1_PREV_CYCLE : INT; // Cycle time of previous OB 1 scan (milliseconds)
  161. OB1_MIN_CYCLE : INT; // Minimum cycle time of OB 1 (milliseconds)
  162. OB1_MAX_CYCLE : INT; // Maximum cycle time of OB 1 (milliseconds)
  163. OB1_DATE_TIME : DATE_AND_TIME; // Date and time OB 1 started
  164. END_VAR
  165. BEGIN
  166. U "clock_100ms"
  167. = E 0.0
  168. U "clock_200ms"
  169. = E 0.1
  170. L L#31337
  171. T ED 2
  172. U A 0.0
  173. = E 0.2
  174. CALL "Ringpuffer", "DB_Ringpuffer" (
  175. eingabe := E 0.0,
  176. ausgabe := E 0.1,
  177. eingabe_wert := ED 2,
  178. reset := E 0.2,
  179. ausgabe_wert := AD 2,
  180. ueberlauf := A 0.0,
  181. unterlauf := A 0.1,
  182. fuellstand := AW 6,
  183. )
  184. L ED 2
  185. L AD 2
  186. L AW 6
  187. END_ORGANIZATION_BLOCK