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