diff --git a/include/serial.h b/include/serial.h new file mode 100644 index 000000000..910c92f0b --- /dev/null +++ b/include/serial.h @@ -0,0 +1,166 @@ +/*****************************************************************************/ +/* */ +/* serial.h */ +/* */ +/* Serial communication API */ +/* */ +/* */ +/* */ +/* (C) 2003 Ullrich von Bassewitz */ +/* Römerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#ifndef _SERIAL_H +#define _SERIAL_H + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Baudrate settings */ +#define SER_BAUD_45_5 0x00 +#define SER_BAUD_50 0x01 +#define SER_BAUD_75 0x02 +#define SER_BAUD_110 0x03 +#define SER_BAUD_134_5 0x04 +#define SER_BAUD_150 0x05 +#define SER_BAUD_300 0x06 +#define SER_BAUD_600 0x07 +#define SER_BAUD_1200 0x08 +#define SER_BAUD_1800 0x09 +#define SER_BAUD_2400 0x0A +#define SER_BAUD_4800 0x0B +#define SER_BAUD_9600 0x0C +#define SER_BAUD_19200 0x0D +#define SER_BAUD_38400 0x0E +#define SER_BAUD_57600 0x0F +#define SER_BAUD_115200 0x10 +#define SER_BAUD_230400 0x11 + +/* Data bit settings */ +#define SER_BITS_5 0x00 +#define SER_BITS_6 0x01 +#define SER_BITS_7 0x02 +#define SER_BITS_8 0x03 + +/* Stop bit settings */ +#define SER_STOP_1 0x00 /* One stop bit */ +#define SER_STOP_2 0x01 /* Two stop bits */ + +/* Parity settings */ +#define SER_PAR_NONE 0x00 +#define SER_PAR_ODD 0x01 +#define SER_PAR_EVEN 0x02 +#define SER_PAR_MARK 0x03 +#define SER_PAR_SPACE 0x04 + +/* Handshake settings. The latter two may be combined. */ +#define SER_HS_NONE 0x00 /* No handshake */ +#define SER_HS_HW 0x01 /* Hardware (RTS/CTS) handshake */ +#define SER_HS_SW 0x02 /* Software handshake */ + +/* Bit masks to mask out things from the status returned by rs232_status */ +#define SER_STATUS_PE 0x01 /* Parity error */ +#define SER_STATUS_FE 0x02 /* Framing error */ +#define SER_STATUS_OE 0x04 /* Overrun error */ +#define SER_STATUS_DCD 0x20 /* NOT data carrier detect */ +#define SER_STATUS_DSR 0x40 /* NOT data set ready */ + +/* Error codes returned by all functions */ +#define SER_ERR_OK 0x00 /* Not an error - relax */ +#define SER_ERR_NO_DRIVER 0x01 /* No driver available */ +#define SER_ERR_CANNOT_LOAD 0x02 /* Error loading driver */ +#define SER_ERR_INV_DRIVER 0x03 /* Invalid driver */ +#define SER_ERR_NO_DEVICE 0x04 /* Device (hardware) not found */ +#define SER_ERR_BAUD_UNAVAIL 0x05 /* Baud rate not available */ +#define SER_ERR_NO_DATA 0x06 /* Nothing to read */ +#define SER_ERR_OVERFLOW 0x07 /* No room in send buffer */ +#define SER_ERR_INIT_FAILED 0x08 /* Initialization failed */ + +/* Struct containing parameters for the serial port */ +struct ser_params { + unsigned char baudrate; /* Baudrate */ + unsigned char databits; /* Number of data bits */ + unsigned char stopbits; /* Number of stop bits */ + unsigned char parity; /* Parity setting */ + unsigned char handshake; /* Type of handshake to use */ +}; + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +unsigned char __fastcall__ ser_load_driver (const char* driver); +/* Load and install a serial driver. Return an error code. */ + +unsigned char __fastcall__ ser_unload (void); +/* Uninstall, then unload the currently loaded driver. */ + +unsigned char __fastcall__ ser_install (void* driver); +/* Install an already loaded driver. Return an error code. */ + +unsigned char __fastcall__ ser_uninstall (void); +/* Uninstall the currently loaded driver and return an error code. + * Note: This call does not free allocated memory. + */ + +unsigned char __fastcall__ ser_params (const struct ser_params* params); +/* Set the port parameters. This will also enable the port. */ + +unsigned char __fastcall__ ser_get (char* b); +/* Get a character from the serial port. If no characters are available, the + * function will return SER_ERR_NO_DATA, so this is not a fatal error. + */ + +unsigned char __fastcall__ ser_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 + * SER_ERR_OVERFLOW if there is no space left in the transmit buffer. + */ + +unsigned char __fastcall__ ser_pause (void); +/* Assert flow control and disable interrupts. */ + +unsigned char __fastcall__ ser_unpause (void); +/* Re-enable interrupts and release flow control */ + +unsigned char __fastcall__ rs232_status (unsigned char* status); +/* Return the serial port status. */ + + + +/* End of serial.h */ +#endif + + + diff --git a/libsrc/serial/Makefile b/libsrc/serial/Makefile new file mode 100644 index 000000000..ab723cf15 --- /dev/null +++ b/libsrc/serial/Makefile @@ -0,0 +1,40 @@ +# +# Makefile for the serial driver API +# + +.SUFFIXES: .o .s .c + +#-------------------------------------------------------------------------- +# Rules + +%.o: %.c + @$(CC) $(CFLAGS) $< + @$(AS) -g -o $@ $(AFLAGS) $(*).s + +%.o: %.s + @$(AS) -g -o $@ $(AFLAGS) $< + +#-------------------------------------------------------------------------- +# Object files + +C_OBJS = ser_load.o + +S_OBJS = ser-kernel.o \ + ser_unload.o + + +#-------------------------------------------------------------------------- +# Targets + +.PHONY: all clean zap + +all: $(C_OBJS) $(S_OBJS) + +clean: + @rm -f *~ + @rm -f $(C_OBJS:.o=.s) + @rm -f $(C_OBJS) + @rm -f $(S_OBJS) + +zap: clean + diff --git a/libsrc/serial/ser-kernel.s b/libsrc/serial/ser-kernel.s new file mode 100644 index 000000000..a1ac462a8 --- /dev/null +++ b/libsrc/serial/ser-kernel.s @@ -0,0 +1,97 @@ +; +; Ullrich von Bassewitz, 2003-04-15 +; +; Common functions of the serial drivers +; + + .export ser_clear_ptr + .import return0 + .importzp ptr1 + + .include "ser-kernel.inc" + .include "ser-error.inc" + + +;---------------------------------------------------------------------------- +; Variables + + +.bss +_ser_drv: .res 2 ; Pointer to driver + +; Jump table for the driver functions. +.data +ser_vectors: +ser_install: jmp return0 +ser_uninstall: jmp return0 + +; Driver header signature +.rodata +ser_sig: .byte $73, $65, $72, $00 ; "ser", version +ser_sig_len = * - ser_sig + + +;---------------------------------------------------------------------------- +; unsigned char __fastcall__ ser_install (void* driver); +; /* Install the driver once it is loaded */ + + +_ser_install: + sta _ser_drv + sta ptr1 + stx _ser_drv+1 + stx ptr1+1 + +; Check the driver signature + + ldy #ser_sig_len-1 +@L0: lda (ptr1),y + cmp ser_sig,y + bne inv_drv + dey + bpl @L0 + +; Copy the jump vectors + + ldy #SER_HDR_JUMPTAB + ldx #0 +@L1: inx ; Skip the JMP opcode + jsr copy ; Copy one byte + jsr copy ; Copy one byte + cpx #(SER_HDR_JUMPCOUNT*3) + bne @L1 + + jmp ser_install ; Call driver install routine + +; Driver signature invalid + +inv_drv: + lda #SER_ERR_INV_DRIVER + ldx #0 + rts + +; Copy one byte from the jump vectors + +copy: lda (ptr1),y + sta ser_vectors,x + iny + inx + rts + +;---------------------------------------------------------------------------- +; unsigned char __fastcall__ ser_uninstall (void); +; /* Uninstall the currently loaded driver and return an error code. +; * Note: This call does not free allocated memory. +; */ + +_ser_uninstall: + jsr ser_uninstall ; Call driver routine + +ser_clear_ptr: ; External entry point + lda #0 + sta _ser_drv + sta _ser_drv+1 ; Clear the driver pointer + + tax + rts ; Return zero + diff --git a/libsrc/serial/ser_load.c b/libsrc/serial/ser_load.c new file mode 100644 index 000000000..580f826fe --- /dev/null +++ b/libsrc/serial/ser_load.c @@ -0,0 +1,82 @@ +/*****************************************************************************/ +/* */ +/* ser_load.c */ +/* */ +/* Loader module for serial drivers */ +/* */ +/* */ +/* */ +/* (C) 2003 Ullrich von Bassewitz */ +/* Römerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#include +#include +#include +#include +#include + + + +unsigned char __fastcall__ ser_load_driver (const char* name) +/* Load a serial driver and return an error code */ +{ + static struct mod_ctrl ctrl = { + read /* Read from disk */ + }; + unsigned char Res; + + /* Check if we do already have a driver loaded. If so, remove it. */ + if (ser_drv != 0) { + ser_uninstall (); + } + + /* Now open the file */ + ctrl.callerdata = open (name, O_RDONLY); + if (ctrl.callerdata >= 0) { + + /* Load the module */ + Res = mod_load (&ctrl); + + /* Close the input file */ + close (ctrl.callerdata); + + /* Check the return code */ + if (Res == MLOAD_OK) { + + /* Check the driver signature, install the driver */ + return ser_install (ctrl.module); + + } + } + + /* Error loading the driver */ + return SER_ERR_CANNOT_LOAD; +} + + + + diff --git a/libsrc/serial/ser_unload.s b/libsrc/serial/ser_unload.s new file mode 100644 index 000000000..6dbad90cd --- /dev/null +++ b/libsrc/serial/ser_unload.s @@ -0,0 +1,31 @@ +; +; Ullrich von Bassewitz, 2003-04-15 +; +; unsigned char __fastcall__ ser_unload (void); +; /* Unload the currently loaded driver. */ + + + .import ser_clear_ptr + + .include "ser-kernel.inc" + .include "ser-error.inc" + .include "modload.inc" + +_ser_unload: + lda _ser_drv + ora _ser_drv+1 + beq no_driver ; No driver + + jsr ser_uninstall ; Deinstall the driver + + lda _ser_drv + ldx _ser_drv+1 + jsr _mod_free ; Free the driver + + jmp ser_clear_ptr ; Clear the driver pointer, return zero + +no_driver: + tax ; X = 0 + lda #SER_ERR_NO_DRIVER + rts +