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