RS.MOD 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. (*========================================================
  2. == JPI-TopSpeed Modula-2 V2 ==
  3. == demo program: ==
  4. == ==
  5. == Example RS232 module ==
  6. == ==
  7. ========================================================*)
  8. (*# call(o_a_copy=>off) *)
  9. (*# check(stack=>off,index=>off,range=>off,overflow=>off,nil_ptr=>off) *)
  10. IMPLEMENTATION MODULE rs;
  11. (*==*)
  12. IMPORT SYSTEM, Lib;
  13. CONST Com1 = 3F8H;
  14. Com1INr = 4;
  15. Com2 = 2F8H;
  16. Com2INr = 3;
  17. IntEnable = 1;
  18. DivisorMsb = 1;
  19. IntId = 2;
  20. LineCont = 3;
  21. ModemCont = 4;
  22. LineStatus = 5;
  23. ModemStatus = 6;
  24. Debug = TRUE;
  25. TYPE b = SET OF SHORTCARD[0..7];
  26. VAR IOBase,ComINr : CARDINAL;
  27. CONST
  28. TXBuffer ::= IOBase;
  29. RXBuffer ::= IOBase;
  30. DivisorLsb ::= IOBase;
  31. BufferSize = 256;
  32. TRMax = BufferSize-16;
  33. Noise = FALSE;
  34. VAR
  35. OldC : FarADDRESS;
  36. Term : PROC;
  37. (*# save, data(volatile=>on) *)
  38. TXReady,CTS,CTSH : BOOLEAN;
  39. RTS : BOOLEAN;
  40. TXCount,TXI,TXO : CARDINAL;
  41. RXCount,RXI,RXO : CARDINAL;
  42. (*# restore *)
  43. IBuf,OBuf : ARRAY[0..BufferSize-1] OF SHORTCARD;
  44. PROCEDURE WrStr(string: ARRAY OF CHAR);
  45. VAR R : SYSTEM.Registers;
  46. i : CARDINAL;
  47. BEGIN
  48. IF Debug THEN
  49. i := 0;
  50. WHILE (i<SIZE(string))AND(string[i]<>CHR(0)) DO
  51. R.AL := SHORTCARD(string[i]);
  52. R.AH := 14;
  53. R.BL := 0;
  54. Lib.Intr( R ,10H );
  55. INC(i);
  56. END;
  57. END;
  58. END WrStr;
  59. PROCEDURE WrLn;
  60. TYPE
  61. a3 = ARRAY [0..1] OF CHAR;
  62. CONST
  63. crlf = a3(CHR(13),CHR(10));
  64. BEGIN
  65. WrStr( crlf );
  66. END WrLn;
  67. PROCEDURE TX;
  68. BEGIN
  69. IF CTS OR NOT CTSH THEN
  70. TXReady := FALSE;
  71. DEC(TXCount);
  72. SYSTEM.Out( TXBuffer,OBuf[TXO] );
  73. TXO := (TXO+1) MOD BufferSize;
  74. END;
  75. END TX;
  76. PROCEDURE RX;
  77. BEGIN
  78. IF RXCount >= TRMax THEN
  79. SYSTEM.Out( IOBase+ModemCont, SHORTCARD( b{0,3} ) );
  80. RTS := FALSE;
  81. END;
  82. IBuf[RXI] := SYSTEM.In( RXBuffer );
  83. IF Noise AND (Lib.RANDOM(500)=0) THEN
  84. IBuf[RXI] := SHORTCARD(Lib.RANDOM(256));
  85. END;
  86. RXI := (RXI+1) MOD BufferSize;
  87. INC(RXCount);
  88. END RX;
  89. VAR GotBreak : BOOLEAN;
  90. (* pragmas for interrupt handler *)
  91. (*# save,
  92. call(interrupt => on,
  93. reg_param => (),
  94. same_ds => off
  95. )
  96. *)
  97. PROCEDURE Int;
  98. VAR i : SHORTCARD;
  99. s : b;
  100. BEGIN
  101. LOOP
  102. i := SYSTEM.In( IOBase+IntId );
  103. IF i=1 THEN EXIT; END;
  104. CASE i DIV 2 OF
  105. | 0 : (* Modem status *)
  106. s := b(SYSTEM.In( IOBase+ModemStatus ));
  107. CTS :=4 IN s;
  108. IF CTS AND (TXCount >0) AND TXReady THEN TX END;
  109. | 1 : (* TXEmpty *)
  110. TXReady := TRUE;
  111. IF TXCount > 0 THEN TX; END;
  112. | 2 : (* RXReady *)
  113. RX;
  114. | 3 : (* LineStatus *)
  115. s := b(SYSTEM.In( IOBase+LineStatus ));
  116. IF 1 IN s THEN WrStr('OR-Error'); WrLn; END;
  117. IF 2 IN s THEN WrStr('PE-Error'); WrLn; END;
  118. IF 4 IN s THEN WrStr('Break'); WrLn;
  119. ELSIF 3 IN s THEN WrStr('FE-Error'); WrLn;
  120. END;
  121. ELSE
  122. WrStr('Unknown Int'); WrLn;
  123. END;
  124. END;
  125. SYSTEM.Out(20H,20H);
  126. END Int;
  127. (*# restore *)
  128. PROCEDURE RxCount():CARDINAL;
  129. BEGIN
  130. RETURN RXCount;
  131. END RxCount;
  132. PROCEDURE TxCount():CARDINAL;
  133. BEGIN
  134. RETURN TXCount;
  135. END TxCount;
  136. PROCEDURE TxFree ():CARDINAL;
  137. BEGIN
  138. RETURN TRMax-TXCount;
  139. END TxFree;
  140. VAR lc : SHORTCARD;
  141. PROCEDURE Break( Time : CARDINAL );
  142. BEGIN
  143. SYSTEM.Out( IOBase+LineCont,SHORTCARD( b(SYSTEM.In(IOBase+LineCont))+b{6})) ;
  144. Lib.Delay( Time );
  145. SYSTEM.Out( IOBase+LineCont,SHORTCARD( b(SYSTEM.In(IOBase+LineCont))-b{6}));
  146. END Break;
  147. PROCEDURE Init( Baud : CARDINAL;
  148. WordLength : wl;
  149. Parity : pt;
  150. OneStopBit : BOOLEAN;
  151. HandShake : BOOLEAN);
  152. VAR d : CARDINAL; i : SHORTCARD;
  153. BEGIN
  154. SYSTEM.DI;
  155. TXI := 0;
  156. TXO := 0;
  157. RXI := 0;
  158. RXO := 0;
  159. RXCount := 0;
  160. TXCount := 0;
  161. SYSTEM.EI;
  162. CTSH := HandShake;
  163. lc := (WordLength-5) MOD 4;
  164. IF NOT OneStopBit THEN lc := lc+4; END;
  165. CASE Parity OF
  166. | None :;
  167. | Even : lc := lc+18H;
  168. | Odd : lc := lc+ 8H;
  169. | Mark : lc := lc+38H;
  170. | Space : lc := lc+28H;
  171. END;
  172. SYSTEM.Out( IOBase+LineCont,80H );
  173. d := CARDINAL( 115200 DIV LONGCARD( Baud ) );
  174. SYSTEM.Out( DivisorLsb, SHORTCARD(d));
  175. SYSTEM.Out( IOBase+DivisorMsb, SHORTCARD(d DIV 100H));
  176. SYSTEM.Out( IOBase+LineCont,lc );
  177. TXReady := TRUE;
  178. SYSTEM.Out( IOBase+ModemCont,SHORTCARD(b{0,1,3}));
  179. CTS := 4 IN b(SYSTEM.In( IOBase+ModemStatus ));
  180. LOOP
  181. i := SYSTEM.In( IOBase+IntId );
  182. IF i=1 THEN EXIT; END;
  183. CASE i DIV 2 OF
  184. | 0 : (* Modem status *)
  185. i := SYSTEM.In( IOBase+ModemStatus );
  186. | 1 : (* TXEmpty *)
  187. | 2 : (* RXReady *)
  188. | 3 : (* LineStatus *)
  189. i := SYSTEM.In( IOBase+LineStatus );
  190. END;
  191. END;
  192. END Init;
  193. PROCEDURE Receive(VAR Buf : ARRAY OF BYTE; Len : CARDINAL );
  194. VAR i : CARDINAL;
  195. BEGIN
  196. FOR i := 0 TO Len-1 DO
  197. WHILE RXCount = 0 DO END;
  198. Buf[i] := IBuf[RXO];
  199. DEC( RXCount );
  200. RXO := (RXO+1) MOD BufferSize;
  201. END;
  202. IF NOT RTS AND (RXCount < TRMax-16) THEN
  203. SYSTEM.Out( IOBase+ModemCont, SHORTCARD( b{0,1,3} ) );
  204. RTS := TRUE;
  205. END;
  206. END Receive;
  207. (*# call(o_a_copy=>off) *)
  208. PROCEDURE Send( Buf : ARRAY OF BYTE; Len : CARDINAL );
  209. VAR i : CARDINAL;
  210. BEGIN
  211. FOR i := 0 TO Len-1 DO
  212. OBuf[TXI] := Buf[i];
  213. INC(TXCount);
  214. WHILE TXCount=BufferSize DO END;
  215. TXI := (TXI+1) MOD BufferSize;
  216. IF TXReady THEN TX; END;
  217. END;
  218. END Send;
  219. VAR
  220. IntTab[0:0] : ARRAY[0..255] OF FarADDRESS;
  221. PROCEDURE CloseDown;
  222. BEGIN
  223. SYSTEM.Out( IOBase+IntEnable,00H );
  224. SYSTEM.Out( IOBase+ModemCont,SHORTCARD(b{}));
  225. Lib.Delay(100);
  226. SYSTEM.DI;
  227. IntTab[8+ComINr] := OldC;
  228. SYSTEM.EI;
  229. Term;
  230. END CloseDown;
  231. PROCEDURE Install( Port : CARDINAL );
  232. BEGIN
  233. IF Port= 1 THEN
  234. Install2( Com1,Com1INr );
  235. ELSE
  236. Install2( Com2,Com2INr );
  237. END;
  238. END Install;
  239. PROCEDURE Install2( Port,Intr : CARDINAL);
  240. TYPE bs = SET OF SHORTCARD[0..7];
  241. VAR s : SHORTCARD; i : CARDINAL;
  242. fa : FarADDRESS;
  243. BEGIN
  244. SYSTEM.DI;
  245. IOBase := Port;
  246. ComINr := Intr;
  247. SYSTEM.Out( IOBase+IntEnable,00H );
  248. SYSTEM.Out( IOBase+LineStatus,0 );
  249. TXI := 0;
  250. TXO := 0;
  251. RXI := 0;
  252. RXO := 0;
  253. RXCount := 0;
  254. TXCount := 0;
  255. OldC := IntTab[8+ComINr];
  256. IntTab[8+ComINr] := FarADR(Int);
  257. Lib.Terminate( CloseDown,Term );
  258. SYSTEM.NewPriority( CARDINAL(BITSET( SYSTEM.CurrentPriority() )-{ComINr} ) );
  259. TXReady := TRUE;
  260. RTS := TRUE;
  261. SYSTEM.Out( IOBase+IntEnable,0BH );
  262. SYSTEM.Out( IOBase+ModemCont,SHORTCARD(b{0,1,3}));
  263. SYSTEM.EI;
  264. END Install2;
  265. PROCEDURE BreakTest():BOOLEAN;
  266. BEGIN
  267. RETURN 4 IN b(SYSTEM.In( IOBase+LineStatus ));
  268. END BreakTest;
  269. BEGIN
  270. lc := SYSTEM.In( IOBase+LineCont );
  271. END rs.
  272.