aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@trantor.hos.anvin.org>2009-01-06 21:47:00 -0800
committerH. Peter Anvin <hpa@trantor.hos.anvin.org>2009-01-06 21:47:00 -0800
commit53acd7741afbf5be3e2b2042ce5ff085e90ebec8 (patch)
tree7ffbea13dc24386055a89a39ee906ea889e1d03d
parent9a543f3c52184488f5c9451298130afc124e8ccc (diff)
downloadabc80-53acd7741afbf5be3e2b2042ce5ff085e90ebec8.tar.gz
abc80-53acd7741afbf5be3e2b2042ce5ff085e90ebec8.tar.xz
abc80-53acd7741afbf5be3e2b2042ce5ff085e90ebec8.zip
Snapshot the file operations work
Snapshot the file operations work. Basic block download now works (I'm even testing this by downloading new versions of printer.bin via a small BASIC stub.) "turbo mode" (460800 bps) doesn't seem to work, however, not really sure why. Not that it really matters. Plenty of more work to be done, though.
-rw-r--r--CHANGES24
-rw-r--r--abc80.v3
-rw-r--r--data/Makefile4
-rwxr-xr-xdata/mmuinit.pl4
-rw-r--r--data/printer.asm286
-rw-r--r--printer.v14
-rw-r--r--tools/abcprint.txt7
-rw-r--r--tools/abcprintd.c29
-rw-r--r--tools/fileop.c26
9 files changed, 360 insertions, 37 deletions
diff --git a/CHANGES b/CHANGES
index 60cd4d6..78b13a6 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,27 @@
+Changes in release DE1-14:
+--------------------------
+* File transfers via abcprintd:
+
+ If abcprintd is started with the -d option, the ABC80 can transfer
+ files to and from a specific directory:
+
+ abcprintd [-t] -d directory /dev/ttySx [print command...]
+
+ On Cygwin, the port number is the Windows port number minus 1,
+ e.g. if Windows calls your USB serial dongle "COM7", you should
+ refer to it as /dev/ttyS6.
+
+ If you have a USB serial dongle or other device capable of
+ nonstandard speeds, you can set SW2 and give abcprintd the "-t"
+ option; this runs the port at 460800 bps instead of 115200.
+
+ You have to reflash your ABC80 ROM (abc80rom.bin) for the file
+ transfer feature, since it has new code for the printer option ROM.
+
+ To use it, access files on the device PRA: for ASCII mode transfer,
+ or PRB: for binary/block mode transfer.
+
+
Changes in release DE1-13:
--------------------------
* Reset the audio DAC before programming it. That way we avoid
diff --git a/abc80.v b/abc80.v
index 618e446..3c3e995 100644
--- a/abc80.v
+++ b/abc80.v
@@ -647,7 +647,8 @@ module abc80 (
.abc_rst_n ( abc_in_n[7] ),
.abc_do ( cpu_do ),
.abc_di ( abc_pr_di ),
- .select ( pr_select )
+ .select ( pr_select ),
+ .turbo ( sw[2] )
);
// The terminology gets a bit funny there. abc_do means data from
diff --git a/data/Makefile b/data/Makefile
index a3c9399..0ddc8b6 100644
--- a/data/Makefile
+++ b/data/Makefile
@@ -8,7 +8,7 @@ Z80ASM = ../tools/z80asm/z80asm
$(Z80ASM) -o $@ -l $*.lst $<
all : keyboard.mif abc80rom.bin basic80.mif \
- mmu.mif chargen.mif videoram.mif sddrom.mif printer.mif \
+ mmu.mif chargen.mif videoram.mif sddrom.mif \
abcsefi.bas abcdkno.bas abcintl.bas
abc80rom.bin : buildrom.pl abcbasic.rom ufddos.bin printer.bin
@@ -38,7 +38,7 @@ sddrom.mif : sddrom.bin $(BIN2MIF)
$(PERL) $(BIN2MIF) 1024 8 < $< > $@ || ( rm -f $@ ; exit 1 )
printer.mif : printer.bin $(BIN2MIF)
- $(PERL) $(BIN2MIF) 512 8 < $< > $@ || ( rm -f $@ ; exit 1 )
+ $(PERL) $(BIN2MIF) 768 8 < $< > $@ || ( rm -f $@ ; exit 1 )
mmu.mif : mmuinit.pl
$(PERL) mmuinit.pl > $@ || ( rm -f $@ ; exit 1 )
diff --git a/data/mmuinit.pl b/data/mmuinit.pl
index fbbc84f..2b3eaa9 100755
--- a/data/mmuinit.pl
+++ b/data/mmuinit.pl
@@ -69,10 +69,10 @@ for ( $i = 0x60 ; $i < 0x74 ; $i++ ) { # DOS, IEC options
for ( $i = 0x74 ; $i < 0x78 ; $i++ ) { # Video RAM (for 80 col only)
printf("%03X : %04X;\n", $a++, 0x2000|($i-0x74));
}
-for ( $i = 0x78 ; $i < 0x7A ; $i++ ) { # PR option
+for ( $i = 0x78 ; $i < 0x7B ; $i++ ) { # PR option
printf("%03X : %04X;\n", $a++, 0x1000|$i);
}
-for ( $i = 0x7A ; $i < 0x7C ; $i++ ) { # RAM (would be PR option)
+for ( $i = 0x7B ; $i < 0x7C ; $i++ ) { # RAM in the PR option area
printf("%03X : %04X;\n", $a++, 0x0000|$i);
}
for ( $i = 0x7C ; $i < 0x80 ; $i++ ) { # Video RAM
diff --git a/data/printer.asm b/data/printer.asm
index 60f7b64..55e5e52 100644
--- a/data/printer.asm
+++ b/data/printer.asm
@@ -5,11 +5,12 @@
; interface:
;
; - ABC-bus select code 60 decimal;
-; OUT 0 - (OUT) data
-; INP 1 - (STAT) bit 5 - sending data
-; bit 6 - receive data (used elsewhere by a simple network
-; protocol)
-; bit 7 - flow control
+; OUT 0 - (OUT) output data
+; OUT 4 - (C3) reset input FIFO
+; IN 0 - (INP) input data
+; INP 1 - (STAT) bit 5 - Tx busy
+; bit 6 - Rx available
+; bit 7 - flow control
;
; Convert FF -> FF FF and send FF 00 on CLOSE.
;
@@ -29,6 +30,9 @@ pr_jptable:
jp nothere ; DELETE???
jp nothere ; RENAME???
+prab_jp_init:
+ jp prab_init
+
pr_open:
call select
@@ -71,23 +75,22 @@ pr_print_not_ff:
inc hl
jr pr_print_loop
- ;
- ; IMPORTANT: This uses register E to save the previous select code.
- ; If register E is used, you must PUSH DE/POP DE or equivalent.
- ;
select:
ld a,(0xFD3F) ; Old select code
- ld e,a
+ ld (ram_select),a ; Save old select code
ld a,selcode ; Select code
ld (0xFD3F),a
out (1),a
ret
wait_busy:
+ push af
+wb_loop:
in a,(1)
and 0A0h ; TX busy or TX flow control
- ret z
- jr wait_busy
+ jr nz,wb_loop
+ pop af
+ ret
nothere:
rst 0x10
@@ -98,11 +101,266 @@ notready:
defb 128+51 ; Err 51 = enheten upptagen
done:
- ld a,e ; Restore select
+ xor a
+done_err:
+ push af
+ ld a,(ram_select)
ld (0xFD3F),a
out (1),a
+ pop af
+ and a
+ ret p
+ scf
+ ret
+
+ ; jp table for PRA:
+pra_jptable:
+ jp pra_open ; OPEN
+ jp pra_prepare ; PREPARE
+ jp pra_close ; CLOSE
+ jp pra_input ; INPUT
+ jp pra_print ; PRINT
+ jp nothere ; Block to buf
+ jp nothere ; Block from buf
+ jp nothere ; DELETE???
+ jp nothere ; RENAME???
+
+prb_jptable:
+ jp prb_open ; OPEN
+ jp prb_prepare ; PREPARE
+ jp prb_close ; CLOSE
+ jp 0015h ; INPUT
+ jp 001Bh ; PRINT
+ jp prb_rdblk ; Block to buf
+ jp prb_wrblk ; Block from buf
+ jp nothere ; DELETE???
+ jp nothere ; RENAME???
+
+pra_open:
+ ld c,0xA0
+ jr prx_open
+prb_open:
+ call prb_setup_buf
+ ld c,0xA1
+ jr prx_open
+pra_prepare:
+ ld c,0xA2
+ jr prx_open
+prb_prepare:
+ call prb_setup_buf
+ ld c,0xA3
+prx_open:
+ push bc
+ ex de,hl ; HL <- filename
+ ld (ix+6),0
+ ld (ix+7),255
+ call select
+ pop bc
+ ld a,c
+ push bc
+ call send_cmd
+ ld bc,11
+ call send_buf
+ pop bc
+ ld a,c
+ push bc
+ call recv_reply
+ and a
+ pop bc
+ jr nz,done_err2
+ bit 0,c ; PRB:?
+ jr z,done2
+ ld l,(ix+8)
+ ld h,(ix+9)
+ ld (hl),0xe0 ; Mark DOSBUF in use, drive no 0xE0
+done2:
+ jp done
+
+prb_close:
+ bit 7,(ix+14)
+ call nz,prb_wrblk
+ ld h,0xFD
+ ld a,0x41
+ add (ix+12)
+ ld l,a
+ ld (hl),0xFF ; Mark buffer free
+pra_close:
+ call select
+ ld a,0xA7
+ call send_cmd
+ ld a,0xA7
+ call recv_reply
+ jr done_err2
+
+pra_print:
+ call select
+ ld a,0xA6
+ call send_cmd
+ ld a,c
+ call send_byte
+ ld a,b
+ call send_byte
+ call send_buf
+ call recv_reply
+done_err2:
+ jp done_err
+
+pra_input:
+prb_wrblk:
+prb_rdblk:
+ scf ; Not implemented yet
+ ret
+
+ ; Set up a BUF for PRB:
+prb_setup_buf:
+ push hl
+ ld hl,0xFD51 ; DOSDEV1
+psb_loop:
+ ld a,(hl)
+ inc a
+ jr z,psb_found
+ ld a,l
+ add 10h
+ ld l,a
+ cp 0C1h
+ jr nz,psb_loop
+ pop hl
+ rst 10h
+ defb 128+19 ; Too many files open
+psb_found:
+ push de
+ ld a,l
+ sub 041h
+ ld (ix+12),a ; DOSDEV*16
+ rrca
+ rrca
+ rrca
+ rrca
+ ld h,a
+ ld l,0
+ ld (ix+14),l
+ ld de,(0xFD12) ; Address to DOSBUF1
+ add hl,de
+ ld (ix+8),l
+ ld (ix+9),h
+ ld (ix+10),l
+ ld (ix+11),h
+ ld (ix+13),253
+ pop de
+ pop hl
+ ret
- and a ; C flag <- 0
+ ; Send a single byte
+send_byte:
+ call wait_busy
+ out (0),a
ret
+ ; Send a command header, A = command
+send_cmd:
+ push af
+ out (4),a ; Clear input FIFO
+
+ ld a,255
+ call send_byte
+ pop af
+ ld (ram_cmd),a
+ call send_byte
+ ld a,(ram_serial)
+ inc a
+ ld (ram_serial),a
+ call send_byte
+ defb 0xdd ; IXL
+ ld a,l
+ call send_byte
+ defb 0xdd ; IXH
+ ld a,h
+ jr send_byte
+
+ ; Send a buffer HL->data BC=count
+ ; On return HL advanced, BC=0, A clobbered
+send_buf:
+ ld a,b
+ or c
+ ret z
+ ld a,(hl)
+ call send_byte
+ dec bc
+ inc hl
+ jr send_buf
+
+ ; Receive a byte. Return with C flag on timeout.
+recv_byte:
+ push bc
+ ld b,0 ; 256/50 Hz = 5.12 s
+rb_ctr:
+ ld a,(65008)
+ ld c,a
+rb_loop:
+ in a,(1)
+ and 64
+ jr nz,rb_data
+ ld a,(65008)
+ cp c
+ jr z,rb_loop
+ djnz rb_ctr
+ pop bc
+ scf
+ ret
+rb_data:
+ in a,(0)
+ ; C flag is 0 already
+ pop bc
+ ret
+
+ ; Receive a reply header.
+ ; Error, if any, in A. ERR 51 if no reply
+recv_reply:
+ push bc
+ call recv_byte
+ jr c,rr_timeout
+ inc a
+ jr nz,recv_reply
+ call recv_byte
+ jr c,rr_timeout
+ ld bc,(ram_cmd)
+ cp c ; Command
+ jr nz,recv_reply
+ call recv_byte
+ jr c,rr_timeout
+ cp b ; Serial
+ jr nz,recv_reply
+ call recv_byte
+ jr nc,rr_done
+rr_timeout:
+ ld a,51+128
+rr_done:
+ pop bc
+ ret
+
+ram_devlst: equ 7B00h
+ram_select: equ 7B0Eh ; Previous select code
+ram_cmd: equ 7B0Fh ; Latest sent command
+ram_serial: equ 7B10h ; Latest serial number
+
+prab_init:
+ ld hl,prab_device
+ ld de,ram_devlst
+ ld bc,7*2
+ ldir
+ ld hl,(65034) ; Device list
+ ld (ram_devlst+7),hl
+ ld hl,ram_devlst
+ ld (65034),hl
+ call select
+ ld a,0xA9 ; CLOSE ALL NO REPLY
+ call send_cmd
+ jp done
+prab_device:
+ defw ram_devlst+7
+ defm "PRA"
+ defw pra_jptable
+ defw 0
+ defm "PRB"
+ defw prb_jptable
diff --git a/printer.v b/printer.v
index 8a3053c..2358980 100644
--- a/printer.v
+++ b/printer.v
@@ -52,7 +52,8 @@ module printer (
abc_do, // ABC-bus data out (cpu->card)
abc_di, // ABC-bus data in (card->cpu)
- select // Select LED
+ select, // Select LED
+ turbo // Turbo switch
);
input reset_n;
@@ -77,6 +78,7 @@ module printer (
output [7:0] abc_di;
output select;
+ input turbo;
// Which select code this device uses
parameter selectcode = 6'd60;
@@ -89,8 +91,11 @@ module printer (
assign tty_txd = tx_data_out;
// Baud rate divider
- parameter baud_rate = 115200;
- parameter baud_div = (25000000/baud_rate)-1;
+ parameter baud_rate_norml = 115200;
+ parameter baud_div_norml = (25000000/baud_rate_norml)-1;
+ parameter baud_rate_turbo = 460800;
+ parameter baud_div_turbo = (25000000/baud_rate_turbo)-1;
+ wire [7:0] baud_div = turbo ? baud_div_turbo : baud_div_norml;
reg [7:0] baud_rate_ctr;
// Time to advance the serial register
wire advance_bit = ~|baud_rate_ctr;
@@ -207,7 +212,8 @@ module printer (
if (~rx_deglitched)
begin
rx_bit_ctr <= 4'd1;
- rx_wait_ctr <= baud_div/2; // Sample near the center point
+ // Sample near the center point; half a cycle delay
+ rx_wait_ctr <= {1'b0, baud_div[7:1]};
end
end
else
diff --git a/tools/abcprint.txt b/tools/abcprint.txt
index 6c16971..ca2e9b3 100644
--- a/tools/abcprint.txt
+++ b/tools/abcprint.txt
@@ -48,7 +48,12 @@ FF A7 ss ixix CLOSE
Close a file handle
-FF A8 ss xxxx CLOSEALL
+FF A8 ss xxxx CLOSE ALL
All files are closed and forgotten. xxxx ignored.
+FF A9 ss xxxx CLOSE ALL NO REPLY
+
+ All files are closed and forgotten. xxxx ignored.
+ No response token is sent.
+
diff --git a/tools/abcprintd.c b/tools/abcprintd.c
index 15ff502..554b4eb 100644
--- a/tools/abcprintd.c
+++ b/tools/abcprintd.c
@@ -27,6 +27,13 @@
#include <sys/wait.h>
#include <fcntl.h>
+#ifndef O_TEXT
+# define O_TEXT 0
+#endif
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
static int lpr_argc;
static const char **lpr_argv;
@@ -70,13 +77,13 @@ static void print_setup(FILE **tfp, enum print_state *psp)
*psp = ps_first;
}
-static int open_port(const char *path)
+static int open_port(const char *path, speed_t speed)
{
struct termios tio;
int fd;
int flags;
- if ( (fd = open(path, O_RDWR|O_NONBLOCK)) < 0 )
+ if ( (fd = open(path, O_RDWR|O_NONBLOCK|O_BINARY)) < 0 )
return -1;
if ( tcgetattr(fd, &tio) )
@@ -96,8 +103,9 @@ static int open_port(const char *path)
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
- cfsetispeed(&tio, B115200);
- cfsetospeed(&tio, B115200);
+
+ cfsetispeed(&tio, speed);
+ cfsetospeed(&tio, speed);
tcflush(fd, TCIFLUSH);
@@ -194,14 +202,18 @@ int main(int argc, char *argv[])
extern char *optarg;
extern int optind, opterr, optopt;
bool badopt = false;
+ speed_t speed = B115200;
file_op_dir = NULL;
- while ((o = getopt(argc, argv, "d:")) != EOF) {
+ while ((o = getopt(argc, argv, "d:t")) != EOF) {
switch (o) {
case 'd':
file_op_dir = optarg;
break;
+ case 't':
+ speed = B460800;
+ break;
default:
badopt = true;
break;
@@ -210,12 +222,15 @@ int main(int argc, char *argv[])
if ( badopt || optind >= argc ) {
fprintf(stderr,
- "Usage: %s [options] port lpr_program [lpr_args...]]\n",
+ "Usage: %s [options] port lpr_program [lpr_args...]]\n"
+ "Options:\n"
+ " -d dir enable file access to directory dir\n"
+ " -t turbo mode (460800 bps)\n",
argv[0]);
exit(1);
}
- if ( (fd = open_port(argv[optind])) < 0 ) {
+ if ( (fd = open_port(argv[optind], speed)) < 0 ) {
perror(argv[optind]);
exit(1);
}
diff --git a/tools/fileop.c b/tools/fileop.c
index ccb3b13..9237c49 100644
--- a/tools/fileop.c
+++ b/tools/fileop.c
@@ -58,15 +58,18 @@ struct file_data {
static void send_reply(int fd, int status)
{
- char reply[4];
+ unsigned char reply[4];
reply[0] = 0xff;
reply[1] = cmd[0];
reply[2] = cmd[1];
reply[3] = status;
- if (fd >= 0)
+ if (fd >= 0) {
xwrite(fd, reply, 4);
+ fprintf(stderr, "Sending reply: %02X %02X %02X %02X\n",
+ reply[0], reply[1], reply[2], reply[3]);
+ }
}
static void do_close(int fd, uint16_t ix)
@@ -85,12 +88,14 @@ static void do_close(int fd, uint16_t ix)
static void do_closeall(int fd)
{
- int i;
+ int ix;
- for (i = 0; i <= 65535; i++)
- do_close(-1, i);
+ for (ix = 0; ix <= 65535; ix++)
+ if (filemap[ix])
+ do_close(-1, ix);
- send_reply(fd, 0);
+ if (cmd[0] == 0xA8)
+ send_reply(fd, 0);
}
/* XXX: This assumes Latin-1; Unicode requires more sophistication */
@@ -235,6 +240,14 @@ static void do_read_block(int fd, uint16_t ix, uint16_t len)
}
send_reply(fd, 0);
+
+ {
+ int16_t c = 0;
+ int i;
+ for (i = 0; i < len; i++)
+ c += data[i+2];
+ fprintf(stderr, "sending %d bytes, checksum %d\n", len, c);
+ }
data[0] = len;
data[1] = len >> 8;
xwrite(fd, data, len+2);
@@ -382,6 +395,7 @@ bool file_op(unsigned char c, int fd)
break;
case 0xA8: /* CLOSEALL */
+ case 0xA9:
do_closeall(fd);
break;