]> git.sur5r.net Git - cc65/blob - libsrc/atari/rs232.s
Don't add a mode when opening files for reading
[cc65] / libsrc / atari / rs232.s
1 ;
2 ; Christian Groessler, Dec-2001
3 ;
4 ; RS232 routines using the R: device (currently tested with an 850 only)
5 ;
6 ; unsigned char __fastcall__ rs232_init (char hacked);
7 ; unsigned char __fastcall__ rs232_params (unsigned char params, unsigned char parity);
8 ; unsigned char __fastcall__ rs232_done (void);
9 ; unsigned char __fastcall__ rs232_get (char* B);
10 ; unsigned char __fastcall__ rs232_put (char B);
11 ; unsigned char __fastcall__ rs232_pause (void); [TODO]
12 ; unsigned char __fastcall__ rs232_unpause (void); [TODO]
13 ; unsigned char __fastcall__ rs232_status (unsigned char* status,
14 ;                                          unsigned char* errors); [TODO]
15 ;
16
17         .import         findfreeiocb
18         .import         __do_oserror
19         .import         fddecusage
20         .import         fdtoiocb
21         .import         __inviocb
22         .import         clriocb
23         .import         newfd
24         .import         _close, pushax, popax, popa
25         .importzp       ptr1, tmp2, tmp3
26
27         .export         _rs232_init, _rs232_params, _rs232_done, _rs232_get
28         .export         _rs232_put, _rs232_pause, _rs232_unpause, _rs232_status
29
30         .include        "atari.inc"
31         .include        "errno.inc"
32         .include        "rs232.inc"
33
34         .rodata
35
36 rdev:   .byte   "R:", ATEOL, 0
37
38         .bss
39
40 ; receive buffer
41 RECVBUF_SZ = 256
42 recv_buf: .res  RECVBUF_SZ
43
44 cm_run: .res    1       ; concurrent mode running?
45
46         .data
47
48 rshand: .word   $ffff
49
50         .code
51
52 ;----------------------------------------------------------------------------
53 ;
54 ; unsigned char __fastcall__ rs232_init (char hacked);
55 ; /* Initialize the serial port. The parameter is ignored in the Atari version.
56 ;  * return 0/-1 for OK/Error
57 ;  */
58 ;
59
60 .proc   _rs232_init
61
62         jsr     findfreeiocb
63         bne     init_err
64         txa
65         tay                     ; move iocb # into Y
66         lda     #3
67         sta     tmp3            ; name length + 1
68         lda     #<rdev
69         ldx     #>rdev
70         jsr     newfd
71         tya
72         bcs     doopen          ; C set: open needed / device not already open
73
74         pha
75         jsr     _rs232_done     ;** shut down if started  @@@TODO check this out!!
76         pla
77
78 doopen: tax
79         pha
80         jsr     clriocb
81         pla
82         tax
83         lda     #<rdev
84         sta     ICBAL,x
85         lda     #>rdev
86         sta     ICBAH,x
87         lda     #OPEN
88         sta     ICCOM,x
89
90         lda     #$0D            ; mode in+out+concurrent
91         sta     ICAX1,x
92         lda     #0
93         sta     ICAX2,x
94         sta     ICBLL,x         ; zap buf len
95         sta     ICBLH,x
96         jsr     CIOV
97         bmi     cioerr1
98
99         lda     tmp2            ; get fd
100         sta     rshand
101         ldx     #0
102         stx     rshand+1
103         txa
104         rts
105
106 cioerr1:jsr     fddecusage      ; decrement usage counter of fd as open failed
107
108 init_err:
109         ldx     #0
110         lda     #RS_ERR_INIT_FAILED
111         rts
112
113 .endproc        ; _rs232_init
114
115
116 ;----------------------------------------------------------------------------
117 ;
118 ; unsigned char __fastcall__ rs232_params (unsigned char params, unsigned char parity);
119 ;
120 ; Set communication parameters.
121 ;
122 ; params contains baud rate, stop bits and word size
123 ; parity contains parity
124 ;
125 ; 850 manual documents restrictions on the baud rate (not > 300), when not
126 ; using 8 bit word size. So only 8 bit is currently tested.
127 ;
128
129 .proc   _rs232_params
130
131         sta     tmp2
132         lda     rshand
133         cmp     #$ff
134         bne     work            ; work only if initialized
135         lda     #RS_ERR_NOT_INITIALIZED
136         bne     done
137 work:   lda     rshand
138         ldx     #0
139         jsr     fdtoiocb        ; get iocb index into X
140         bmi     inverr          ; shouldn't happen
141         tax
142
143         ; set handshake lines
144
145         lda     #34             ; xio 34, set cts, dtr etc
146         sta     ICCOM,x
147         lda     #192+48+3       ; DTR on, RTS on, XMT on
148         sta     ICAX1,x
149         lda     #0
150         sta     ICBLL,x
151         sta     ICBLH,x
152         sta     ICBAL,x
153         sta     ICBAH,x
154         sta     ICAX2,x
155         jsr     CIOV
156         bmi     cioerr
157
158         ; set baud rate, word size, stop bits and ready monitoring
159
160         lda     #36             ; xio 36, baud rate
161         sta     ICCOM,x
162         jsr     popa            ; get parameter
163         sta     ICAX1,x
164         ;ICAX2 = 0, monitor nothing
165         jsr     CIOV
166         bmi     cioerr
167
168         ; set translation and parity
169
170         lda     #38             ; xio 38, translation and parity
171         sta     ICCOM,x
172         lda     tmp2
173         ora     #32             ; no translation
174         sta     ICAX1,x
175         jsr     CIOV
176         bmi     cioerr
177
178         lda     #0
179 done:   ldx     #0
180         rts
181
182 inverr: jmp     __inviocb
183
184 .endproc        ;_rs232_params
185
186 cioerr: jmp     __do_oserror
187
188
189 ;----------------------------------------------------------------------------
190 ;
191 ; unsigned char __fastcall__ rs232_done (void);
192 ; /* Close the port, deinstall the interrupt hander. You MUST call this function
193 ;  * before terminating the program, otherwise the machine may crash later. If
194 ;  * in doubt, install an exit handler using atexit(). The function will do
195 ;  * nothing, if it was already called.
196 ;  */
197 ;
198
199 .proc   _rs232_done
200
201         lda     rshand
202         cmp     #$ff
203         beq     done
204 work:   ldx     rshand+1
205         jsr     pushax
206         jsr     _close
207         pha
208         txa
209         pha
210         ldx     #$ff
211         stx     rshand
212         stx     rshand+1
213         inx
214         stx     cm_run
215         pla
216         tax
217         pla
218 done:   rts
219
220 .endproc        ;rs232_done
221
222
223 ;----------------------------------------------------------------------------
224 ;
225 ; unsigned char __fastcall__ rs232_get (char* B);
226 ; /* Get a character from the serial port. If no characters are available, the
227 ;  * function will return RS_ERR_NO_DATA, so this is not a fatal error.
228 ;  */
229 ;
230
231 .proc   _rs232_get
232
233         ldy     rshand
234         cpy     #$ff
235         bne     work            ; work only if initialized
236         lda     #RS_ERR_NOT_INITIALIZED
237         bne     nierr
238
239 work:   sta     ptr1
240         stx     ptr1+1          ; store pointer to received char
241
242         lda     rshand
243         ldx     #0
244         jsr     fdtoiocb
245         tax
246         lda     cm_run          ; concurrent mode already running?
247         bne     go
248         jsr     ena_cm          ; turn on concurrent mode
249
250 go:     ; check whether there is any input available
251
252         lda     #STATIS         ; status request, returns bytes pending
253         sta     ICCOM,x
254         jsr     CIOV
255         bmi     cioerr          ; @@@ error handling
256
257         lda     DVSTAT+1        ; get byte count pending
258         ora     DVSTAT+2
259         beq     nix_da          ; no input waiting...
260
261         ; input is available: get it!
262
263         lda     #GETCHR         ; get raw bytes
264         sta     ICCOM,x         ; in command code
265         lda     #0
266         sta     ICBLL,x
267         sta     ICBLH,x
268         sta     ICBAL,x
269         sta     ICBAH,x
270         jsr     CIOV            ; go get it
271         bmi     cioerr          ; @@@ error handling
272
273         ldx     #0
274         sta     (ptr1,x)        ; return received byte
275         txa
276         rts
277
278 nierr:  ldx     #0
279         rts
280
281 nix_da: lda     #RS_ERR_NO_DATA
282         ldx     #0
283         rts
284
285 .endproc        ;_rs232_get
286
287
288 ;----------------------------------------------------------------------------
289 ;
290 ; unsigned char __fastcall__ rs232_put (char B);
291 ; /* Send a character via the serial port. There is a transmit buffer, but
292 ;  * transmitting is not done via interrupt. The function returns
293 ;  * RS_ERR_OVERFLOW if there is no space left in the transmit buffer.
294 ;  */
295 ;
296
297 .proc   _rs232_put
298
299         ldy     rshand
300         cpy     #$ff
301         bne     work            ; work only if initialized
302         lda     #RS_ERR_NOT_INITIALIZED
303         bne     nierr
304
305 work:   pha
306         lda     rshand
307         ldx     #0
308         jsr     fdtoiocb
309         tax
310         lda     cm_run          ; concurrent mode already running?
311         bne     go
312         jsr     ena_cm          ; turn on concurrent mode
313
314         ; @@@TODO:       check output buffer overflow
315 go:     lda     #PUTCHR         ; put raw bytes
316         sta     ICCOM,x         ; in command code
317         lda     #0
318         sta     ICBLL,x
319         sta     ICBLH,x
320         sta     ICBAL,x
321         sta     ICBAH,x
322         pla                     ; get the char back
323         jsr     CIOV            ; go do it
324         rts
325
326 nierr:  ldx     #0
327         rts
328
329 .endproc        ;_rs232_put
330
331 ;----------------------------------------------------------------------------
332 ;
333 ; unsigned char __fastcall__ rs232_pause (void);
334 ; /* Assert flow control and disable interrupts. */
335 ;
336
337 _rs232_pause:
338
339
340 ;----------------------------------------------------------------------------
341 ;
342 ; unsigned char __fastcall__ rs232_unpause (void);
343 ; /* Re-enable interrupts and release flow control */
344 ;
345
346 _rs232_unpause:
347
348
349 ;----------------------------------------------------------------------------
350 ;
351 ; unsigned char __fastcall__ rs232_status (unsigned char* status,
352 ;                                          unsigned char* errors);
353 ; /* Return the serial port status. */
354 ;
355
356 _rs232_status:
357
358         lda     #255
359         tax
360         rts
361
362
363 ; enable concurrent rs232 mode
364 ; gets iocb index in X
365 ; all registers destroyed
366
367 .proc   ena_cm
368
369         lda     #40             ; XIO 40, start concurrent IO
370         sta     ICCOM,x
371         sta     cm_run          ; indicate concurrent mode is running
372         lda     #0
373         sta     ICAX1,x
374         sta     ICAX2,x
375         lda     #<recv_buf
376         sta     ICBAL,x
377         lda     #>recv_buf
378         sta     ICBAH,x
379         lda     #<RECVBUF_SZ
380         sta     ICBLL,x
381         lda     #>RECVBUF_SZ
382         sta     ICBLH,x
383         lda     #$0D            ; value from 850 man, p62.  must be 0D?,
384         sta     ICAX1,x         ;  or any non-zero?
385         jmp     CIOV
386
387 .endproc        ;ena_cm
388
389         .end