-CSRCS = devlpr.c devtty.c devfd.c
+CSRCS = devlpr.c devtty.c devfd.c devdw.c
CSRCS += devices.c main.c libc.c
-ASRCS = p6809.s crt0.s
+ASRCS = p6809.s crt0.s drivewire.s
ASRCS += tricks.s commonmem.s usermem_sam.s floppy.s
COBJS = $(CSRCS:.c=$(BINEXT))
crt0.o commonmem.o usermem_sam.o \
p6809.o ../start.o ../version.o ../lowlevel-6809.o \
tricks.o main.o ../timer.o ../kdata.o devfd.o floppy.o devices.o \
+ drivewire.o devdw.o \
../devio.o ../filesys.o ../process.o ../inode.o ../syscall_fs.o \
../syscall_proc.o ../syscall_other.o ../mm.o ../swap.o ../simple.o \
../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o ../syscall_exec16.o \
Disks
-Not supported yet.
+Virtual disk drives over "DriveWire" are supported. For real machines
+it uses a bit-banging serial interface on the printer port.
+For XRoar it is using the Becker interface, which is supported by the
+DW4 server by Aaron Wolfe https://sites.google.com/site/drivewire4/
+
+Real disk controllers are not supported yet.
With an expander we should look across all the cartridges to find out which
one is us and which one (should be slot #4) contains a cartridge with DK at
Also to consider
-DriveWire - over Beckerport - serial 'virtual disk' protocol
-
CoCoSDC: SDC virtual disk including LBA mode interface for SD hard disk and
also flash for catridge slots (banked). Looks ideal but not documented
usefully.
RSDOS: WD1793
-Becker port at 0xFF40 (FF46 ? on Dragon)
+Hardware Becker port at 0xFF40 (FF46 ? on Dragon)
IDE: FF70-FF78 - data latched (write high/load, read low/high) [0-7 IDE regs
8 maps the latches]
--- /dev/null
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devdw.h>
+
+#define MAX_DW 4 /* can be 255 */
+
+#define DW_READ 0
+#define DW_WRITE 1
+
+static uint8_t dw_tab[MAX_DW];
+
+/*
+ * Block device glue for DriveWire
+ *
+ * DriveWire uses 256 byte sector transfers
+ */
+
+static int dw_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
+{
+ blkno_t block;
+ uint16_t dptr;
+ int ct = 0;
+ int tries;
+ uint8_t err;
+ uint8_t *driveptr = dw_tab + minor;
+ uint8_t cmd[5];
+
+ if(rawflag)
+ goto bad2;
+
+ dptr = (uint16_t)udata.u_buf->bf_data;
+ block = udata.u_buf->bf_blk;
+
+// kprintf("Issue command: drive %d\n", minor);
+ /* maybe mimicking floppy driver more than needed? */
+ cmd[0] = is_read ? DW_READ : DW_WRITE;
+ cmd[1] = block >> 7; /* 2 sectors per block */
+ cmd[2] = (block << 1) & 0xFF;
+ cmd[3] = dptr >> 8;
+ cmd[4] = dptr & 0xFF;
+ *driveptr = minor; /* pass minor (drive number) through here for now */
+
+ while (ct < 2) {
+ for (tries = 0; tries < 4 ; tries++) {
+ // kprintf("dw_operation on block %d ct %d\n", block, ct);
+ err = dw_operation(cmd, driveptr);
+ if (err == 0)
+ break;
+ if (tries > 1)
+ dw_reset(driveptr);
+ }
+ /* FIXME: should we try the other half and then bail out ? */
+ if (tries == 3)
+ goto bad;
+ cmd[3]++; /* Move on 256 bytes in the buffer */
+ cmd[2]++; /* Next sector for 2nd block */
+ ct++;
+ }
+ return 1;
+bad:
+ kprintf("dw%d: error %x\n", minor, err);
+bad2:
+ udata.u_error = EIO;
+ return -1;
+}
+
+/* FIXME: for bit-banger transport (not Becker) we should set up
+ the PIA at some point too */
+
+int dw_open(uint8_t minor, uint16_t flag)
+{
+ if(minor >= MAX_DW) {
+ udata.u_error = ENODEV;
+ return -1;
+ }
+ return 0;
+}
+
+int dw_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
+{
+ return dw_transfer(minor, true, rawflag);
+}
+
+int dw_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
+{
+ return dw_transfer(minor, false, rawflag);
+}
+
--- /dev/null
+#ifndef __DEVDW_DOT_H__
+#define __DEVDW_DOT_H__
+
+/* public interface */
+int dw_read(uint8_t minor, uint8_t rawflag, uint8_t flag);
+int dw_write(uint8_t minor, uint8_t rawflag, uint8_t flag);
+int dw_open(uint8_t minor, uint16_t flag);
+
+/* low level interface */
+uint8_t dw_reset(uint8_t *drive);
+uint8_t dw_operation(uint8_t *cmd, uint8_t *drive);
+
+#endif /* __DEVDW_DOT_H__ */
+
#include <version.h>
#include <kdata.h>
#include <devfd.h>
+#include <devdw.h>
#include <devsys.h>
#include <devlpr.h>
#include <tty.h>
/* 4: /dev/mem etc System devices (one offs) */
{ no_open, no_close, sys_read, sys_write, sys_ioctl },
/* Pack to 7 with nxio if adding private devices and start at 8 */
+ { nxio_open, no_close, no_rdwr, no_rdwr, no_ioctl },
+ { nxio_open, no_close, no_rdwr, no_rdwr, no_ioctl },
+ { nxio_open, no_close, no_rdwr, no_rdwr, no_ioctl },
+ /* 8: /dev/dw DriveWire remote disk images */
+ { dw_open, no_close, dw_read, dw_write, no_ioctl },
};
bool validdev(uint16_t dev)
--- /dev/null
+;
+; DriveWire sector routines
+;
+; Copyright 2015 Tormod Volden
+; Copyright 2008 Boisy G. Pitre
+; Distributed under the GNU General Public License, version 2 or later.
+;
+
+ ; exported
+ .globl _dw_operation
+ .globl _dw_reset
+
+ .area .text
+
+_dw_reset:
+ ; maybe reinitalise PIA here?
+ ; and send DW_INIT request to server?
+ rts
+
+_dw_operation:
+ pshs y
+ ; get parameters from C, X points to cmd packet
+ ldy 4,s ; driveptr
+ lda ,y ; for now, contains minor = drive number directly
+ ldb ,x ; write flag
+ ; buffer location into Y
+ ldy 3,x
+ ; sector number into X
+ ldx 1,x
+ tstb
+ bne @write
+ jsr dw_read_sector
+ bra @done
+@write jsr dw_write_sector
+@done bcs @err
+ bne @err
+ ldx #0
+@ret puls y,pc
+@err ldx #0xFFFF
+ bra @ret
+
+; Write a sector to the DriveWire server
+; Drive number in A, sector number in X, buffer location in Y
+; Sets carry or non-zero flags on error
+dw_write_sector:
+ ; header: OP, drive = A, LSN 23-16 = 0, LSN 15-8 and LSN 7-0 = X
+ clrb
+ pshs a,b,x
+ ldb #OP_WRITE
+ pshs b
+ ; send header
+ tfr s,x
+ pshs y ; save buffer location
+ ldy #5
+ jsr DWWrite
+ ; send payload
+ ldx ,s
+ ldy #256
+ jsr DWWrite
+ ; calculate checksum of payload, backwards
+ exg x,y ; Y is zero after DWWrite
+@sum ldb ,-y
+ abx
+ cmpy ,s ; buffer location start
+ bne @sum
+ stx ,s ; checksum to send
+ tfr s,x
+ ldy #2
+ jsr DWWrite
+ ; get status byte from server into following byte
+ ldy #1
+ clra ; clear carry bit for BECKER variant
+ jsr DWRead
+ leas 7,s
+ bcs @ret
+ bne @ret
+ ldb -5,s ; received status byte (zero is success)
+@ret rts
+
+;
+; Based on "DoRead" by Boisy G. Pitre from DWDOS hosted on toolshed.sf.net
+; Read a sector from the DriveWire server
+; Drive number in A, 16-bit sector in X, buffer location in Y
+; Sets carry or non-zero flags on error
+
+dw_read_sector:
+ ; header: OP, drive = A, LSN 23-16 = 0, LSN 15-8 and LSN 7-0 = X
+ clrb
+ pshs d,x,y
+ lda #OP_READEX
+ReRead pshs a
+ leax ,s
+ ldy #$0005
+ lbsr DWWrite
+ puls a
+ ldx 4,s get read buffer pointer
+ ldy #256 read 256 bytes
+ ldd #133*1 1 second timeout
+ bsr DWRead
+ bcs ReadEx
+ bne ReadEx
+; Send 2 byte checksum
+ pshs y
+ leax ,s
+ ldy #2
+ lbsr DWWrite
+ ldy #1
+ ldd #133*1
+ bsr DWRead
+ leas 2,s
+ bcs ReadEx
+ bne ReadEx
+; Check received status byte
+ lda ,s
+ beq ReadEx
+ cmpa #E_CRC
+ bne ReadErr
+ lda #OP_REREADEX
+ clr ,s
+ bra ReRead
+ReadErr comb ; set carry bit
+ReadEx puls d,x,y,pc
+
+; Used by DWRead and DWWrite
+IntMasks equ $50
+NOINTMASK equ 1
+
+; Hardcode these for now so that we can use below files unmodified
+H6309 equ 0
+BECKER equ 1
+ARDUINO equ 0
+JMCPBCK equ 0
+BAUD38400 equ 0
+
+; These files are copied almost as-is from HDB-DOS
+ include "dw.def"
+ include "dwread.s"
+ include "dwwrite.s"
+
--- /dev/null
+********************************************************************
+*
+* Copied from HDB-DOS from toolshed.sf.net
+*
+* dwdefs - DriveWire Definitions File
+*
+* $Id: dwdefs.d,v 1.10 2010/02/21 06:24:47 aaronwolfe Exp $
+*
+* Ed. Comments Who YY/MM/DD
+* ------------------------------------------------------------------
+* 1 Started BGP 03/04/03
+* 2 Added DWGLOBS area BGP 09/12/27
+
+ nam dwdefs
+ ttl DriveWire Definitions File
+
+* Addresses
+BBOUT equ $FF20
+BBIN equ $FF22
+
+* Opcodes
+OP_NOP equ $00 No-Op
+OP_RESET1 equ $FE Server Reset
+OP_RESET2 equ $FF Server Reset
+OP_RESET3 equ $F8 Server Reset
+OP_DWINIT equ 'Z DriveWire dw3 init/OS9 boot
+OP_TIME equ '# Current time requested
+OP_INIT equ 'I Init routine called
+OP_READ equ 'R Read one sector
+OP_REREAD equ 'r Re-read one sector
+OP_READEX equ 'R+128 Read one sector
+OP_REREADEX equ 'r+128 Re-read one sector
+OP_WRITE equ 'W Write one sector
+OP_REWRIT equ 'w Re-write one sector
+OP_GETSTA equ 'G GetStat routine called
+OP_SETSTA equ 'S SetStat routine called
+OP_TERM equ 'T Term routine called
+OP_SERINIT equ 'E
+OP_SERTERM equ 'E+128
+
+* Printer opcodes
+OP_PRINT equ 'P Print byte to the print buffer
+OP_PRINTFLUSH equ 'F Flush the server print buffer
+
+* Serial opcodes
+OP_SERREAD equ 'C
+OP_SERREADM equ 'c
+OP_SERWRITE equ 'C+128
+OP_SERGETSTAT equ 'D
+OP_SERSETSTAT equ 'D+128
+
+* for dw vfm
+OP_VFM equ 'V+128
+
+* WireBug opcodes (Server-initiated)
+OP_WIREBUG_MODE equ 'B
+* WireBug opcodes (Server-initiated)
+OP_WIREBUG_READREGS equ 'R Read the CoCo's registers
+OP_WIREBUG_WRITEREGS equ 'r Write the CoCo's registers
+OP_WIREBUG_READMEM equ 'M Read the CoCo's memory
+OP_WIREBUG_WRITEMEM equ 'm Write the CoCo's memory
+OP_WIREBUG_GO equ 'G Tell CoCo to get out of WireBug mode and continue execution
+
+* VPort opcodes (CoCo-initiated)
+OP_VPORT_READ equ 'V
+OP_VPORT_WRITE equ 'v
+
+* Error definitions
+E_CRC equ $F3 Same as NitrOS-9 E$CRC
+
--- /dev/null
+*******************************************************
+*
+* Copied from HDB-DOS from toolshed.sf.net
+* The original code is public domain
+*
+* DWRead
+* Receive a response from the DriveWire server.
+* Times out if serial port goes idle for more than 1.4 (0.7) seconds.
+* Serial data format: 1-8-N-1
+* 4/12/2009 by Darren Atkinson
+*
+* Entry:
+* X = starting address where data is to be stored
+* Y = number of bytes expected
+*
+* Exit:
+* CC = carry set on framing error, Z set if all bytes received
+* X = starting address of data received
+* Y = checksum
+* U is preserved. All accumulators are clobbered
+*
+
+ IFNE ARDUINO
+* Note: this is an optimistic routine. It presumes that the server will always be there, and
+* has NO timeout fallback. It is also very short and quick.
+DWRead clra ; clear Carry (no framing error)
+ pshs u,x,cc ; preserve registers
+ leau ,x
+ ldx #$0000
+loop@ tst $FF51 ; check for CA1 bit (1=Arduino has byte ready)
+ bpl loop@ ; loop if not set
+ ldb $FF50 ; clear CA1 bit in status register
+ stb ,u+ ; save off acquired byte
+ abx ; update checksum
+ leay ,-y
+ bne loop@
+
+ leay ,x ; return checksum in Y
+ puls cc,x,u,pc ; restore registers and return
+
+ ELSE
+
+ IFNE JMCPBCK
+* NOTE: There is no timeout currently on here...
+DWRead clra ; clear Carry (no framing error)
+ deca ; clear Z flag, A = timeout msb ($ff)
+ tfr cc,b
+ pshs u,x,dp,b,a ; preserve registers, push timeout msb
+ leau ,x
+ ldx #$0000
+ IFEQ NOINTMASK
+ orcc #IntMasks
+ ENDC
+loop@ ldb $FF4C
+ bitb #$02
+ beq loop@
+ ldb $FF44
+ stb ,u+
+ abx
+ leay ,-y
+ bne loop@
+
+ tfr x,y
+ ldb #0
+ lda #3
+ leas 1,s ; remove timeout msb from stack
+ inca ; A = status to be returned in C and Z
+ ora ,s ; place status information into the..
+ sta ,s ; ..C and Z bits of the preserved CC
+ leay ,x ; return checksum in Y
+ puls cc,dp,x,u,pc ; restore registers and return
+ ELSE
+ IFNE BECKER
+ IFNDEF BCKSTAT
+BCKSTAT equ $FF41
+ ENDC
+ IFNDEF BCKPORT
+BCKPORT equ $FF42
+ ENDC
+* NOTE: There is no timeout currently on here...
+DWRead clra ; clear Carry (no framing error)
+ deca ; clear Z flag, A = timeout msb ($ff)
+ tfr cc,b
+ pshs u,x,dp,b,a ; preserve registers, push timeout msb
+ leau ,x
+ ldx #$0000
+ IFEQ NOINTMASK
+ orcc #IntMasks
+ ENDC
+loop@ ldb BCKSTAT
+ bitb #$02
+ beq loop@
+ ldb BCKPORT
+ stb ,u+
+ abx
+ leay ,-y
+ bne loop@
+ tfr x,y
+ ldb #0
+ lda #3
+timeout leas 1,s ; remove timeout msb from stack
+ inca ; A = status to be returned in C and Z
+ ora ,s ; place status information into the..
+ sta ,s ; ..C and Z bits of the preserved CC
+ leay ,x ; return checksum in Y
+ puls cc,dp,x,u,pc ; restore registers and return
+ ENDC
+ ENDC
+ ENDC
+
+ IFEQ BECKER+JMCPBCK+ARDUINO
+ IFNE BAUD38400
+*******************************************************
+* 38400 bps using 6809 code and timimg
+*******************************************************
+
+DWRead clra ; clear Carry (no framing error)
+ deca ; clear Z flag, A = timeout msb ($ff)
+ tfr cc,b
+ pshs u,x,dp,b,a ; preserve registers, push timeout msb
+ IFEQ NOINTMASK
+ orcc #IntMasks ; mask interrupts
+ ENDC
+ tfr a,dp ; set direct page to $FFxx
+ setdp $ff
+ leau ,x ; U = storage ptr
+ ldx #0 ; initialize checksum
+ adda #2 ; A = $01 (serial in mask), set Carry
+
+* Wait for a start bit or timeout
+rx0010 bcc rxExit ; exit if timeout expired
+ ldb #$ff ; init timeout lsb
+rx0020 bita <BBIN ; check for start bit
+ beq rxByte ; branch if start bit detected
+ subb #1 ; decrement timeout lsb
+ bita <BBIN
+ beq rxByte
+ bcc rx0020 ; loop until timeout lsb rolls under
+ bita <BBIN
+ beq rxByte
+ addb ,s ; B = timeout msb - 1
+ bita <BBIN
+ beq rxByte
+ stb ,s ; store decremented timeout msb
+ bita <BBIN
+ bne rx0010 ; loop if still no start bit
+
+* Read a byte
+rxByte leay ,-y ; decrement request count
+ ldd #$ff80 ; A = timeout msb, B = shift counter
+ sta ,s ; reset timeout msb for next byte
+rx0030 exg a,a
+ nop
+ lda <BBIN ; read data bit
+ lsra ; shift into carry
+ rorb ; rotate into byte accumulator
+ lda #$01 ; prep stop bit mask
+ bcc rx0030 ; loop until all 8 bits read
+
+ stb ,u+ ; store received byte to memory
+ abx ; update checksum
+ ldb #$ff ; set timeout lsb for next byte
+ anda <BBIN ; read stop bit
+ beq rxExit ; exit if framing error
+ leay ,y ; test request count
+ bne rx0020 ; loop if another byte wanted
+ lda #$03 ; setup to return SUCCESS
+
+* Clean up, set status and return
+rxExit leas 1,s ; remove timeout msb from stack
+ inca ; A = status to be returned in C and Z
+ ora ,s ; place status information into the..
+ sta ,s ; ..C and Z bits of the preserved CC
+ leay ,x ; return checksum in Y
+ puls cc,dp,x,u,pc ; restore registers and return
+ setdp $00
+
+
+ ELSE
+ IFNE H6309
+*******************************************************
+* 57600 (115200) bps using 6309 native mode
+*******************************************************
+
+DWRead clrb ; clear Carry (no framing error)
+ decb ; clear Z flag, B = $FF
+ pshs u,x,dp,cc ; preserve registers
+ IFEQ NOINTMASK
+ orcc #IntMasks ; mask interrupts
+ ENDC
+* ldmd #1 ; requires 6309 native mode
+ tfr b,dp ; set direct page to $FFxx
+ setdp $ff
+ leay -1,y ; adjust request count
+ leau ,x ; U = storage ptr
+ tfr 0,x ; initialize checksum
+ lda #$01 ; A = serial in mask
+ bra rx0030 ; go wait for start bit
+
+* Read a byte
+rxByte sexw ; 4 cycle delay
+ ldw #$006a ; shift counter and timing flags
+ clra ; clear carry so next will branch
+rx0010 bcc rx0020 ; branch if even bit number (15 cycles)
+ nop ; extra (16th) cycle
+rx0020 lda <BBIN ; read bit
+ lsra ; move bit into carry
+ rorb ; rotate bit into byte accumulator
+ lda #0 ; prep A for 8th data bit
+ lsrw ; bump shift count, timing bit to carry
+ bne rx0010 ; loop until 7th data bit has been read
+ incw ; W = 1 for subtraction from Y
+ inca ; A = 1 for reading bit 7
+ anda <BBIN ; read bit 7
+ lsra ; move bit 7 into carry, A = 0
+ rorb ; byte is now complete
+ stb ,u+ ; store received byte to memory
+ abx ; update checksum
+ subr w,y ; decrement request count
+ inca ; A = 1 for reading stop bit
+ anda <BBIN ; read stop bit
+ bls rxExit ; exit if completed or framing error
+
+* Wait for a start bit or timeout
+rx0030 clrw ; initialize timeout counter
+rx0040 bita <BBIN ; check for start bit
+ beq rxByte ; branch if start bit detected
+ addw #1 ; bump timeout counter
+ bita <BBIN
+ beq rxByte
+ bcc rx0040 ; loop until timeout rolls over
+ lda #$03 ; setup to return TIMEOUT status
+
+* Clean up, set status and return
+rxExit beq rx0050 ; branch if framing error
+ eora #$02 ; toggle SUCCESS flag
+rx0050 inca ; A = status to be returned in C and Z
+ ora ,s ; place status information into the..
+ sta ,s ; ..C and Z bits of the preserved CC
+ leay ,x ; return checksum in Y
+ puls cc,dp,x,u,pc ; restore registers and return
+ setdp $00
+
+
+ ELSE
+*******************************************************
+* 57600 (115200) bps using 6809 code and timimg
+*******************************************************
+
+DWRead clra ; clear Carry (no framing error)
+ deca ; clear Z flag, A = timeout msb ($ff)
+ tfr cc,b
+ pshs u,x,dp,b,a ; preserve registers, push timeout msb
+ IFEQ NOINTMASK
+ orcc #IntMasks ; mask interrupts
+ ENDC
+ tfr a,dp ; set direct page to $FFxx
+ ;setdp $ff
+ leau ,x ; U = storage ptr
+ ldx #0 ; initialize checksum
+ lda #$01 ; A = serial in mask
+ bra rx0030 ; go wait for start bit
+
+* Read a byte
+rxByte leau 1,u ; bump storage ptr
+ leay ,-y ; decrement request count
+ lda <BBIN ; read bit 0
+ lsra ; move bit 0 into Carry
+ ldd #$ff20 ; A = timeout msb, B = shift counter
+ sta ,s ; reset timeout msb for next byte
+ rorb ; rotate bit 0 into byte accumulator
+rx0010 lda <BBIN ; read bit (d1, d3, d5)
+ lsra
+ rorb
+ bita 1,s ; 5 cycle delay
+ bcs rx0020 ; exit loop after reading bit 5
+ lda <BBIN ; read bit (d2, d4)
+ lsra
+ rorb
+ leau ,u
+ bra rx0010
+
+rx0020 lda <BBIN ; read bit 6
+ lsra
+ rorb
+ leay ,y ; test request count
+ beq rx0050 ; branch if final byte of request
+ lda <BBIN ; read bit 7
+ lsra
+ rorb ; byte is now complete
+ stb -1,u ; store received byte to memory
+ abx ; update checksum
+ lda <BBIN ; read stop bit
+ anda #$01 ; mask out other bits
+ beq rxExit ; exit if framing error
+
+* Wait for a start bit or timeout
+rx0030 bita <BBIN ; check for start bit
+ beq rxByte ; branch if start bit detected
+ bita <BBIN ; again
+ beq rxByte
+ ldb #$ff ; init timeout lsb
+rx0040 bita <BBIN
+ beq rxByte
+ subb #1 ; decrement timeout lsb
+ bita <BBIN
+ beq rxByte
+ bcc rx0040 ; loop until timeout lsb rolls under
+ bita <BBIN
+ beq rxByte
+ addb ,s ; B = timeout msb - 1
+ bita <BBIN
+ beq rxByte
+ stb ,s ; store decremented timeout msb
+ bita <BBIN
+ beq rxByte
+ bcs rx0030 ; loop if timeout hasn't expired
+ bra rxExit ; exit due to timeout
+
+rx0050 lda <BBIN ; read bit 7 of final byte
+ lsra
+ rorb ; byte is now complete
+ stb -1,u ; store received byte to memory
+ abx ; calculate final checksum
+ lda <BBIN ; read stop bit
+ anda #$01 ; mask out other bits
+ ora #$02 ; return SUCCESS if no framing error
+
+* Clean up, set status and return
+rxExit leas 1,s ; remove timeout msb from stack
+ inca ; A = status to be returned in C and Z
+ ora ,s ; place status information into the..
+ sta ,s ; ..C and Z bits of the preserved CC
+ leay ,x ; return checksum in Y
+ puls cc,dp,x,u,pc ; restore registers and return
+ ;setdp $00
+
+ ENDC
+ ENDC
+ ENDC
+
--- /dev/null
+*******************************************************
+*
+* Copied from HDB-DOS from toolshed.sf.net
+* The original code is public domain
+*
+* DWWrite
+* Send a packet to the DriveWire server.
+* Serial data format: 1-8-N-1
+* 4/12/2009 by Darren Atkinson
+*
+* Entry:
+* X = starting address of data to send
+* Y = number of bytes to send
+*
+* Exit:
+* X = address of last byte sent + 1
+* Y = 0
+* All others preserved
+*
+
+
+ IFNE ARDUINO
+DWWrite pshs a ; preserve registers
+txByte
+ lda ,x+ ; get byte from buffer
+ sta $FF52 ; put it to PIA
+loop@ tst $FF53 ; check status register
+ bpl loop@ ; until CB1 is set by Arduino, continue looping
+ tst $FF52 ; clear CB1 in status register
+ leay -1,y ; decrement byte counter
+ bne txByte ; loop if more to send
+
+ puls a,pc ; restore registers and return
+
+ ELSE
+
+ IFNE JMCPBCK
+DWWrite pshs d,cc ; preserve registers
+ IFEQ NOINTMASK
+ orcc #IntMasks ; mask interrupts
+ ENDC
+txByte
+ lda ,x+
+ sta $FF44
+ leay -1,y ; decrement byte counter
+ bne txByte ; loop if more to send
+
+ puls cc,d,pc ; restore registers and return
+
+ ELSE
+ IFNE BECKER
+ IFNDEF BCKPORT
+BCKPORT equ $FF42
+ ENDC
+DWWrite pshs d,cc ; preserve registers
+ IFEQ NOINTMASK
+ orcc #IntMasks ; mask interrupts
+ ENDC
+; ldu #BBOUT ; point U to bit banger out register
+; lda 3,u ; read PIA 1-B control register
+; anda #$f7 ; clear sound enable bit
+; sta 3,u ; disable sound output
+; fcb $8c ; skip next instruction
+
+txByte
+ lda ,x+
+ sta BCKPORT
+ leay -1,y ; decrement byte counter
+ bne txByte ; loop if more to send
+
+ puls cc,d,pc ; restore registers and return
+ ENDC
+ ENDC
+ ENDC
+
+ IFEQ BECKER+JMCPBCK+ARDUINO
+ IFNE BAUD38400
+*******************************************************
+* 38400 bps using 6809 code and timimg
+*******************************************************
+
+DWWrite pshs u,d,cc ; preserve registers
+ IFEQ NOINTMASK
+ orcc #IntMasks ; mask interrupts
+ ENDC
+ ldu #BBOUT ; point U to bit banger out register
+ lda 3,u ; read PIA 1-B control register
+ anda #$f7 ; clear sound enable bit
+ sta 3,u ; disable sound output
+ fcb $8c ; skip next instruction
+
+txByte stb ,--u ; send stop bit
+ leau ,u+
+ lda #8 ; counter for start bit and 7 data bits
+ ldb ,x+ ; get a byte to transmit
+ lslb ; left rotate the byte two positions..
+ rolb ; ..placing a zero (start bit) in bit 1
+tx0010 stb ,u++ ; send bit
+ tst ,--u
+ rorb ; move next bit into position
+ deca ; decrement loop counter
+ bne tx0010 ; loop until 7th data bit has been sent
+ leau ,u
+ stb ,u ; send bit 7
+ lda ,u++
+ ldb #$02 ; value for stop bit (MARK)
+ leay -1,y ; decrement byte counter
+ bne txByte ; loop if more to send
+
+ stb ,--u ; leave bit banger output at MARK
+ puls cc,d,u,pc ; restore registers and return
+
+ ELSE
+
+ IFNE H6309
+*******************************************************
+* 57600 (115200) bps using 6309 native mode
+*******************************************************
+
+DWWrite pshs u,d,cc ; preserve registers
+ IFEQ NOINTMASK
+ orcc #IntMasks ; mask interrupts
+ ENDC
+* ldmd #1 ; requires 6309 native mode
+ ldu #BBOUT+1 ; point U to bit banger out register +1
+ aim #$f7,2,u ; disable sound output
+ lda #8 ; counter for start bit and 7 data bits
+ fcb $8c ; skip next instruction
+
+txByte stb -1,u ; send stop bit
+tx0010 ldb ,x+ ; get a byte to transmit
+ lslb ; left rotate the byte two positions..
+ rolb ; ..placing a zero (start bit) in bit 1
+ bra tx0030
+
+tx0020 bita #1 ; even or odd bit number ?
+ beq tx0040 ; branch if even (15 cycles)
+tx0030 nop ; extra (16th) cycle
+tx0040 stb -1,u ; send bit
+ rorb ; move next bit into position
+ deca ; decrement loop counter
+ bne tx0020 ; loop until 7th data bit has been sent
+ leau ,u+
+ stb -1,u ; send bit 7
+ ldd #$0802 ; A = loop counter, B = MARK value
+ leay -1,y ; decrement byte counter
+ bne txByte ; loop if more to send
+
+ stb -1,u ; final stop bit
+ puls cc,d,u,pc ; restore registers and return
+
+ ELSE
+*******************************************************
+* 57600 (115200) bps using 6809 code and timimg
+*******************************************************
+
+DWWrite pshs dp,d,cc ; preserve registers
+ IFEQ NOINTMASK
+ orcc #IntMasks ; mask interrupts
+ ENDC
+ ldd #$04ff ; A = loop counter, B = $ff
+ tfr b,dp ; set direct page to $FFxx
+ ;setdp $ff
+ ldb <$ff23 ; read PIA 1-B control register
+ andb #$f7 ; clear sound enable bit
+ stb <$ff23 ; disable sound output
+ fcb $8c ; skip next instruction
+
+txByte stb <BBOUT ; send stop bit
+ ldb ,x+ ; get a byte to transmit
+ nop
+ lslb ; left rotate the byte two positions..
+ rolb ; ..placing a zero (start bit) in bit 1
+tx0020 stb <BBOUT ; send bit (start bit, d1, d3, d5)
+ rorb ; move next bit into position
+ exg a,a
+ nop
+ stb <BBOUT ; send bit (d0, d2, d4, d6)
+ rorb ; move next bit into position
+ leau ,u
+ deca ; decrement loop counter
+ bne tx0020 ; loop until 7th data bit has been sent
+
+ stb <BBOUT ; send bit 7
+ ldd #$0402 ; A = loop counter, B = MARK value
+ leay ,-y ; decrement byte counter
+ bne txByte ; loop if more to send
+
+ stb <BBOUT ; leave bit banger output at MARK
+ puls cc,d,dp,pc ; restore registers and return
+ ;setdp $00
+
+ ENDC
+ ENDC
+ ENDC
+