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