diff --git a/libsrc/atari/rs232.s b/libsrc/atari/rs232.s new file mode 100644 index 000000000..c18afc09a --- /dev/null +++ b/libsrc/atari/rs232.s @@ -0,0 +1,419 @@ +; +; Christian Groessler, Dec-2001 +; +; RS232 routines using the R: device (currently tested with an 850 only) +; +; unsigned char __fastcall__ rs232_init (char hacked); +; unsigned char __fastcall__ rs232_params (unsigned char params, unsigned char parity); +; unsigned char __fastcall__ rs232_done (void); +; unsigned char __fastcall__ rs232_get (char* B); +; unsigned char __fastcall__ rs232_put (char B); +; unsigned char __fastcall__ rs232_pause (void); [TODO] +; unsigned char __fastcall__ rs232_unpause (void); [TODO] +; unsigned char __fastcall__ rs232_status (unsigned char* status, +; unsigned char* errors); [TODO] +; + + .import findfreeiocb + .import __seterrno, __do_oserror, __oserror + .import fddecusage + .import fdtoiocb + .import clriocb + .import newfd + .import _close, pushax, popax + .importzp ptr1, tmp2, tmp3 + + .export _rs232_init, _rs232_params, _rs232_done, _rs232_get + .export _rs232_put, _rs232_pause, _rs232_unpause, _rs232_status + + .include "atari.inc" + .include "../common/errno.inc" + + .rodata + +rdev: .byte "R:", ATEOL, 0 + + .bss + +RECVBUF_SZ = 256 + +; receive buffer +recv_buf: .res RECVBUF_SZ +cm_run: .res 1 ; concurrent mode running? + + .data + +rshand: .word $ffff + + .code + +;---------------------------------------------------------------------------- +; +; unsigned char __fastcall__ rs232_init (char hacked); +; /* Initialize the serial port. The parameter is ignored in the Atari version. +; * return 0/-1 for OK/Error +; */ +; + +.proc _rs232_init + + jsr findfreeiocb + beq iocbok ; we found one + + lda #EMFILE +seterr: jsr __seterrno + lda #$FF + tax + rts ; return -1 + +iocbok: txa + tay ; move iocb # into Y + lda #3 + sta tmp3 ; name length + 1 + lda #rdev + jsr newfd + tya + bcs doopen ; C set: open needed / device not already open + + pha + jsr _rs232_done ;** shut down if started @@@TODO check this out!! + pla + +doopen: tax + pha + jsr clriocb + pla + tax + lda #rdev + sta ICBAH,x + lda #OPEN + sta ICCOM,x + + lda #$0D ; mode in+out+concurrent + sta ICAX1,x + lda #0 + sta ICAX2,x + sta ICBLL,x ; zap buf len + sta ICBLH,x + jsr CIOV + bmi cioerr + + lda tmp2 ; get fd + sta rshand + ldx #0 + stx rshand+1 + txa + stx __oserror + rts + +cioerr: jsr fddecusage ; decrement usage counter of fd as open failed + jmp __do_oserror + +.endproc ; _rs232_init + + +;---------------------------------------------------------------------------- +; +; unsigned char __fastcall__ rs232_params (unsigned char params, unsigned char parity); +; /* Set the port parameters. Use a combination of the #defined values above. */ +; +; Set communication parameters. +; +; @@@ C64 values @@@ fixit +; baud rates stops word | parity +; --------------------- ----- ----- | --------- +; $00=50 $08=9600 $00=1 $00=8 | $00=none +; $01=110 $09=19200 $80=2 $20=7 | $20=odd +; $02=134.5 $0a=38400 $40=6 | $60=even +; $03=300 $0b=57600 $60=5 | $A0=mark +; $04=600 $0c=115200 | $E0=space +; $05=1200 $0d=230400 +; $06=2400 $0e=future +; $07=4800 $0f=future +; + +; we don't support word sizes != 8 (will never) +; ignore parity for now, always none +; ignore baud rate for now, always 9600 + +; shouldn't this come from a "rs232.inc" ?? + ErrNotInitialized = $01 + ErrNoData = $04 + +.proc _rs232_params + + lda rshand + cmp #$ff + bne work ; work only if initialized + lda #ErrNotInitialized + bne done +work: lda rshand + ldx #0 + jsr fdtoiocb ; get iocb index into X +; bmi inverr ; !?!? + tax + + ; set handshake lines + + lda #34 ; xio 34, set cts, dtr etc + sta ICCOM,x + lda #192+48+3 ; DTR on, RTS on, XMT on + sta ICAX1,x + lda #0 + sta ICBLL,x + sta ICBLH,x + sta ICBAL,x + sta ICBAH,x + sta ICAX2,x + jsr CIOV + + ; set baud rate, word size, stop bits and ready monitoring + + lda #36 ; xio 36, baud rate + sta ICCOM,x + lda #14 ; 9600 baud + sta ICAX1,x + ;ICAX2 = 0, monitor nothing + jsr CIOV + + ; set translation and parity + + lda #38 ; xio 38, translation and parity + sta ICCOM,x + lda #32 ; no translation, no parity + sta ICAX1,x + jsr CIOV + + lda #0 +done: ldx #0 + rts + +.endproc ;_rs232_params + + +;---------------------------------------------------------------------------- +; +; unsigned char __fastcall__ rs232_done (void); +; /* Close the port, deinstall the interrupt hander. You MUST call this function +; * before terminating the program, otherwise the machine may crash later. If +; * in doubt, install an exit handler using atexit(). The function will do +; * nothing, if it was already called. +; */ +; + +.proc _rs232_done + + lda rshand + cmp #$ff +; bne work +; lda rshand+1 +; cmp #$ff + beq done +work: lda rshand + ldx rshand+1 + jsr pushax + jsr _close + pha + txa + pha + ldx #$ff + stx rshand + stx rshand+1 + inx + stx cm_run + pla + tax + pla +done: rts + +.endproc ;rs232_done + + +;---------------------------------------------------------------------------- +; +; unsigned char __fastcall__ rs232_get (char* B); +; /* Get a character from the serial port. If no characters are available, the +; * function will return RS_ERR_NO_DATA, so this is not a fatal error. +; */ +; + +.import _cputc + +.proc _rs232_get + + ldy rshand + cpy #$ff + bne work ; work only if initialized + lda #ErrNotInitialized + bne nierr + +work: sta ptr1 + stx ptr1+1 ; store pointer to received char + + lda rshand + ldx #0 + jsr fdtoiocb + tax + lda cm_run ; concurrent mode already running? + bne go + jsr ena_cm ; turn on concurrent mode + +go: ; check whether there is any input available + + lda #STATIS ; status request, returns bytes pending + sta ICCOM,x + jsr CIOV +; bmi cioerr ; @@@ error handling + + lda DVSTAT+1 ; get byte count pending + ora DVSTAT+2 + beq nix_da ; no input waiting... + +.ifdef DEBUG + pha + txa + pha + tya + pha + lda #'D' + jsr _cputc + pla + tay + pla + tax + pla +.endif + + ; input is available: get it! + + lda #GETCHR ; get raw bytes + sta ICCOM,x ; in command code + lda #0 + sta ICBLL,x + sta ICBLH,x + sta ICBAL,x + sta ICBAH,x + jsr CIOV ; go get it +; bmi cioerr ; @@@ error handling + + ldx #0 + sta (ptr1,x) ; return received byte + txa + rts + +nierr: ldx #0 + rts + +nix_da: lda #ErrNoData + ldx #0 + rts + +.endproc ;_rs232_get + + +;---------------------------------------------------------------------------- +; +; unsigned char __fastcall__ rs232_put (char B); +; /* Send a character via the serial port. There is a transmit buffer, but +; * transmitting is not done via interrupt. The function returns +; * RS_ERR_OVERFLOW if there is no space left in the transmit buffer. +; */ +; + +.proc _rs232_put + + ldy rshand + cpy #$ff + bne work ; work only if initialized + lda #ErrNotInitialized + bne nierr + +work: pha + lda rshand + ldx #0 + jsr fdtoiocb + tax + lda cm_run ; concurrent mode already running? + bne go + jsr ena_cm ; turn on concurrent mode + + ; @@@TODO: check output buffer overflow +go: lda #PUTCHR ; put raw bytes + sta ICCOM,x ; in command code + lda #0 + sta ICBLL,x + sta ICBLH,x + sta ICBAL,x + sta ICBAH,x + pla ; get the char back + jsr CIOV ; go do it + rts + +nierr: ldx #0 + rts + +.endproc ;_rs232_put + +;---------------------------------------------------------------------------- +; +; unsigned char __fastcall__ rs232_pause (void); +; /* Assert flow control and disable interrupts. */ +; + +_rs232_pause: + + +;---------------------------------------------------------------------------- +; +; unsigned char __fastcall__ rs232_unpause (void); +; /* Re-enable interrupts and release flow control */ +; + +_rs232_unpause: + + +;---------------------------------------------------------------------------- +; +; unsigned char __fastcall__ rs232_status (unsigned char* status, +; unsigned char* errors); +; /* Return the serial port status. */ +; + +_rs232_status: + + lda #255 + tax + rts + + +; enable concurrent rs232 mode +; gets iocb index in X +; all registers destroyed + +.proc ena_cm + + lda #40 ; XIO 40, start concurrent IO + sta ICCOM,x + sta cm_run ; indicate concurrent mode is running + lda #0 + sta ICAX1,x + sta ICAX2,x + lda #recv_buf + sta ICBAH,x + lda #RECVBUF_SZ + sta ICBLH,x + lda #$0D ; value from 850 man, p62. must be 0D?, + sta ICAX1,x ; or any non-zero? + jmp CIOV + +.endproc ;ena_cm + + .end