summaryrefslogtreecommitdiff
path: root/fpcdocs/olinuxex/serial.pp
blob: ed01d4f42ef299f44a81ef034d67ca2da5161c66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
program Terminal_test;
{******************************************************************************
 * Really really budget attempt at Serial IO with Linux and FPC.
 * My first FPC program. Re-built and refined on 12/6/99
 * Written under X windows with nedit 5.0.2 (Not a bad editor)
 * This SHOULD work without including the CRT Unit, However it has problems
 * With reading from the keyboard unless the CRT unit is included ?!?
 *
 * Designed to talk to an RS485 Buss, using RTS as the Tx/Rx Select Pin
 * No Copyrights or warrantys.
 * Let me know if it's of some use to you.
 * Brad Campbell (bcampbel@omen.net.au)
 ******************************************************************************}
uses oldlinux, Crt;

Const DTR : Cardinal = TIOCM_DTR;
Const RTS : Cardinal = TIOCM_RTS;

Var     FD              : Longint;
        InChr           : String[1];
        InStr           : String[80];
        Quit            : Boolean;
        InLen, Loop     : Integer;
        tios            : Termios;
        fds             : FDSet;


Procedure DumpFlags;
begin
IOCtl(FD,TIOCMGET,@tios);
Writeln('Input   Flags    : $',hexstr(tios.c_iflag,8));
Writeln('Output  Flags    : $',hexstr(tios.c_oflag,8));
Writeln('Local   Flags    : $',hexstr(tios.c_lflag,8));
Writeln('Control Flags    : $',hexstr(tios.c_cflag,8));
End;


Procedure RS485RX;
Begin
IOCtl(FD,TIOCMBIS,@RTS);
End;

Procedure RS485TX;
Begin
IOCtl(FD,TIOCMBIC,@RTS);
End;


Procedure DtrOn;
Begin
IOCtl(FD,TIOCMBIS,@DTR);
End;

Procedure DtrOff;
Begin
IOCtl(FD,TIOCMBIC,@DTR);
End;

Procedure SendToRemote(OutString : String);
Begin
Rs485TX;        {Switch Buss to Transmit}
if fdWrite(FD,OutString[1],Length(OutString)) <> Length(OutString) then
        Writeln('Write Error');
{Write(OutString);} {Uncomment for Local Echo}
TCDrain(FD);    {Block Program until all data sent out port has left UART}
RS485RX;        {Switch Buss back to Recieve}
End;


{ Not limited to baud selection I have here, it's just all I use }
Procedure SetBaudrate;
Var     NewBaud : LongInt;
Begin
Writeln;
Writeln('New Baud Rate (300,1200,2400,4800, 9600,19200,38400) ? ');
Readln(NewBaud);
Case NewBaud of
   300 : NewBaud := B300;
  1200 : NewBaud := B1200;
  2400 : NewBaud := B2400;
  4800 : NewBaud := B4800;
  9600 : NewBaud := B9600;
 19200 : NewBaud := B19200;
 38400 : NewBaud := B38400;
Else
        Begin
        Writeln('Invalid Baud Rate. Baud not Changed');
        Writeln;
        NewBaud := 0;
        End;
End;

{ Sets Baud Rate Here }
If NewBaud <> 0 then
        Begin
                IOCtl(FD,TCGETS,@tios);         {Get IOCTL TermIOS Settings}
                CFSetOSpeed(tios,NewBaud);      {Set Relevant Bits}
                IOCtl(FD,TCSETS,@tios);         {Put them back with IOCTL}
                Writeln('New Baudrate ',HexStr(NewBaud,2),' Set');
                {This line just prints what the constant equates to for
                 Information Only}
        End;
End;


Begin
Quit := False;
Writeln('Brad''s Dumb Terminal Test prog v0.2');
Writeln('Ctrl-C to exit program');
Writeln('Ctrl-D to set Baud Rate');
Writeln('Uses /dev/ttyS0 (Com 1)');
Writeln;

FD:=fdOpen('/dev/ttyS0',Open_RdWr or Open_NonBlock or Open_Excl);
{Open Port Read/Write, Not Blocking and Exclusive}

if FD > 0 then Begin

Writeln('Port Open');

FLock(FD,LOCK_EX);
{Attempt to Lock the port, I'm not sure this is strictly nessecary}

Writeln('Port Locked');

{Set Comms Parms, 9600 Baud, 8 Data Bits, Reciever Enabled,
 Modem Control Lines Ignored}
{Read man 3 termios for More options}

IOCtl(FD,TCGETS,@tios);
tios.c_cflag := B9600 Or CS8 Or CREAD Or CLOCAL;
tios.c_lflag := 0;
tios.c_oflag := 0;
tios.c_iflag := 0;
IOCtl(FD,TCSETS,@tios);

DumpFlags;      {This is for information only and dumps the contents of
                 the Termios registers}

Repeat
FD_Zero (FDS);          {Clear File Descriptors Array}
FD_Set (0,FDS);         {Input from Keyboard}
FD_SET (FD,FDS);        {Input from Serial Port}

Select(FD+1,@FDS,nil,nil,nil);  {Will Wait for input from above}

If FD_ISSET(0,FDS) then         {Has there been a key pressed ?}
        If fdRead(0,InChr[1],80) <> 0 then
                Begin
                if InChr[1] = Chr(3) then Quit := True;
                if InChr[1] = Chr(4) then SetBaudRate;
                SendToRemote(InChr[1]);
                End;

If FD_ISSET(FD,FDS) then        {Have we data waiting in UART ? }
        Begin
                InLen := fdRead(FD,InStr[1],80);
                If InLen > 0 then
                For Loop := 1 to Inlen do
                Write(InStr[Loop]);
        End;
Until Quit = True;      {Were Outa Here}
FLock(FD,LOCK_UN);      {Unlock Port}
fdClose(FD);            {Close Port}
End
Else Writeln('Open Port Error');        {We failed to Open/Lock the UART}
End.