1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 07:38:06 +11:00

Compare commits

...

4 Commits

Author SHA1 Message Date
Virgil Dupras
97dcad9b15 recipes/sms/kbd: use Collapse OS' AVR assembler 2020-02-26 23:10:43 -05:00
Virgil Dupras
64a54c72f8 Fix broken recipes 2020-02-26 21:44:37 -05:00
Virgil Dupras
92ddc7ebc1 recipes/trs80: use grid module
Not much of a gain in terms of usability (a bit of a loss in fact, things are
a bit slow and glitchy), but it's a necessary move if we want to use upcoming
grid-enabled userspace apps, such as a visual text editor.
2020-02-26 16:27:27 -05:00
Virgil Dupras
a442c46935 sms/vdp: highlight cursor with inverted palette 2020-02-26 09:43:50 -05:00
20 changed files with 280 additions and 119 deletions

View File

@ -628,19 +628,19 @@ _parseArgs:
_readBit: _readBit:
ld a, 7 ld a, 7
jr _readExpr jp _readExpr
_readA6: _readA6:
ld a, 0x3f ld a, 0x3f
jr _readExpr jp _readExpr
_readA5: _readA5:
ld a, 0x1f ld a, 0x1f
jr _readExpr jp _readExpr
_readK8: _readK8:
ld a, 0xff ld a, 0xff
jr _readExpr jp _readExpr
_readDouble: _readDouble:
push de push de
@ -707,6 +707,12 @@ _readR5:
push de push de
ld a, (hl) ld a, (hl)
call upcase call upcase
cp 'X'
jr z, .rdXYZ
cp 'Y'
jr z, .rdXYZ
cp 'Z'
jr z, .rdXYZ
cp 'R' cp 'R'
jr nz, .end ; not a register jr nz, .end ; not a register
inc hl inc hl
@ -717,6 +723,34 @@ _readR5:
.end: .end:
pop de pop de
ret ret
.rdXYZ:
; First, let's get a base value, that is, (A-'X'+26)*2, because XL, our
; lowest register, is equivalent to r26.
sub 'X'
rla ; no carry from sub
add a, 26
ld d, a ; store that
inc hl
ld a, (hl)
call upcase
cp 'H'
jr nz, .skip1
; second char is 'H'? our value is +1
inc d
jr .skip2
.skip1:
cp 'L'
jr nz, .end ; not L either? then it's not good
.skip2:
; Good, we have our final value in D and we're almost sure it's a valid
; register. Our only check left is that the 3rd char is a null.
inc hl
ld a, (hl)
or a
jr nz, .end
; we're good
ld a, d
jr .end
; Put DE's LSB into A and, additionally, ensure that the new value is <= ; Put DE's LSB into A and, additionally, ensure that the new value is <=
; than what was previously in A. ; than what was previously in A.

View File

@ -1,12 +1,5 @@
; *** CPU registers aliases *** ; *** CPU registers aliases ***
.equ XH 27
.equ XL 26
.equ YH 29
.equ YL 28
.equ ZH 31
.equ ZL 30
.equ SREG_C 0 ; Carry Flag .equ SREG_C 0 ; Carry Flag
.equ SREG_Z 1 ; Zero Flag .equ SREG_Z 1 ; Zero Flag
.equ SREG_N 2 ; Negative Flag .equ SREG_N 2 ; Negative Flag

View File

@ -108,6 +108,9 @@ void create_window()
xcb_map_window(conn, win); xcb_map_window(conn, win);
} }
// To make things simple with X11, we only support monochrome display, which is
// inverted: As soon as the color of the pixel is non-black, we show a black
// pixel. If the pixel is white, we show black.
void draw_pixels() void draw_pixels()
{ {
xcb_get_geometry_reply_t *geom; xcb_get_geometry_reply_t *geom;

View File

@ -51,6 +51,7 @@ void vdp_data_wr(VDP *vdp, uint8_t val)
} }
} }
// Returns a 8-bit RGB value (0b00bbggrr)
uint8_t vdp_pixel(VDP *vdp, uint16_t x, uint16_t y) uint8_t vdp_pixel(VDP *vdp, uint16_t x, uint16_t y)
{ {
if (x >= VDP_SCREENW) { if (x >= VDP_SCREENW) {
@ -63,6 +64,8 @@ uint8_t vdp_pixel(VDP *vdp, uint16_t x, uint16_t y)
uint16_t offset = 0x3800 + ((y/8) << 6) + ((x/8) << 1); uint16_t offset = 0x3800 + ((y/8) << 6) + ((x/8) << 1);
uint16_t tableval = vdp->vram[offset] + (vdp->vram[offset+1] << 8); uint16_t tableval = vdp->vram[offset] + (vdp->vram[offset+1] << 8);
uint16_t tilenum = tableval & 0x1ff; uint16_t tilenum = tableval & 0x1ff;
// is palette select bit on? if yes, use sprite palette instead
uint8_t palettemod = tableval & 0x800 ? 0x10 : 0;
// tile offset this time. Each tile is 0x20 bytes long. // tile offset this time. Each tile is 0x20 bytes long.
offset = tilenum * 0x20; offset = tilenum * 0x20;
// Each 4 byte is a row. Find row first. // Each 4 byte is a row. Find row first.
@ -70,8 +73,10 @@ uint8_t vdp_pixel(VDP *vdp, uint16_t x, uint16_t y)
uint8_t bitnum = 7 - (x%8); uint8_t bitnum = 7 - (x%8);
// Now, let's compose the result by pushing the right bit of our 4 bytes // Now, let's compose the result by pushing the right bit of our 4 bytes
// into our result. // into our result.
return ((vdp->vram[offset] >> bitnum) & 1) + \ uint8_t palette_id = ((vdp->vram[offset] >> bitnum) & 1) + \
(((vdp->vram[offset+1] >> bitnum) & 1) << 1) + \ (((vdp->vram[offset+1] >> bitnum) & 1) << 1) + \
(((vdp->vram[offset+2] >> bitnum) & 1) << 2) + \ (((vdp->vram[offset+2] >> bitnum) & 1) << 2) + \
(((vdp->vram[offset+3] >> bitnum) & 1) << 3); (((vdp->vram[offset+3] >> bitnum) & 1) << 3);
uint8_t rgb = vdp->vram[0x4000+palettemod+palette_id];
return rgb;
} }

View File

@ -12,8 +12,10 @@
; can access those cells by their (X, Y) address. In addition to this, we have ; can access those cells by their (X, Y) address. In addition to this, we have
; the concept of an active cursor, which will be indicated visually if possible. ; the concept of an active cursor, which will be indicated visually if possible.
; ;
; Additionally, this module provides a PutC routine, suitable for plugging into ; This module provides PutC and GetC routines, suitable for plugging into stdio.
; stdio. ; PutC, for obvious reasons, GetC, for less obvious reasons: We need to wrap
; GetC because we need to update the cursor before calling actual GetC, but
; also, because we need to know when a bulk update ends.
; ;
; *** Defines *** ; *** Defines ***
; ;
@ -21,7 +23,9 @@
; GRID_ROWS: Number of rows in the grid ; GRID_ROWS: Number of rows in the grid
; GRID_SETCELL: Pointer to routine that sets cell at row D and column E with ; GRID_SETCELL: Pointer to routine that sets cell at row D and column E with
; character in A. If C is nonzero, this cell must be displayed, ; character in A. If C is nonzero, this cell must be displayed,
; if possible, as the cursor. ; if possible, as the cursor. This routine is never called with
; A < 0x20.
; GRID_GETC: Routine that gridGetC will wrap around.
; ;
; *** Consts *** ; *** Consts ***
.equ GRID_SIZE GRID_COLS*GRID_ROWS .equ GRID_SIZE GRID_COLS*GRID_ROWS
@ -31,6 +35,10 @@
.equ GRID_CURX GRID_RAMSTART .equ GRID_CURX GRID_RAMSTART
; Cursor's row ; Cursor's row
.equ GRID_CURY @+1 .equ GRID_CURY @+1
; Whether we scrolled recently. We don't refresh the screen immediately when
; scrolling in case we have many lines being spit at once (refreshing the
; display is then very slow). Instead, we wait until the next gridGetC call
.equ GRID_SCROLLED @+1
; Grid's in-memory buffer of the contents on screen. Because we always push to ; Grid's in-memory buffer of the contents on screen. Because we always push to
; display right after a change, this is almost always going to be a correct ; display right after a change, this is almost always going to be a correct
; representation of on-screen display. ; representation of on-screen display.
@ -53,7 +61,7 @@ _gridPlaceCell:
ld hl, GRID_BUF ld hl, GRID_BUF
ld a, d ld a, d
or a or a
ret z jr z, .setcol
push de ; --> lvl 1 push de ; --> lvl 1
ld de, GRID_COLS ld de, GRID_COLS
.loop: .loop:
@ -61,10 +69,18 @@ _gridPlaceCell:
dec a dec a
jr nz, .loop jr nz, .loop
pop de ; <-- lvl 1 pop de ; <-- lvl 1
.setcol:
; We're at the proper row, now let's advance to cell ; We're at the proper row, now let's advance to cell
ld a, e ld a, e
jp addHL jp addHL
; Ensure that A >= 0x20
_gridAdjustA:
cp 0x20
ret nc
ld a, 0x20
ret
; Push row D in the buffer onto the screen. ; Push row D in the buffer onto the screen.
gridPushRow: gridPushRow:
push af push af
@ -78,6 +94,7 @@ gridPushRow:
ld b, GRID_COLS ld b, GRID_COLS
.loop: .loop:
ld a, (hl) ld a, (hl)
call _gridAdjustA
; A, C, D and E have proper values ; A, C, D and E have proper values
call GRID_SETCELL call GRID_SETCELL
inc hl inc hl
@ -98,11 +115,10 @@ gridClrRow:
push hl push hl
ld e, 0 ld e, 0
call _gridPlaceCell call _gridPlaceCell
xor a ld a, ' '
ld b, GRID_COLS ld b, GRID_COLS
call fill call fill
call gridPushRow call gridPushRow
pop hl pop hl
pop de pop de
pop bc pop bc
@ -119,7 +135,7 @@ gridPushScr:
pop de pop de
ret ret
; Set character under cursor to A ; Set character under cursor to A. C is passed to GRID_SETCELL as-is.
gridSetCur: gridSetCur:
push de push de
push hl push hl
@ -131,17 +147,34 @@ gridSetCur:
call _gridPlaceCell call _gridPlaceCell
pop af \ push af ; <--> lvl 1 pop af \ push af ; <--> lvl 1
ld (hl), a ld (hl), a
call _gridAdjustA
call GRID_SETCELL call GRID_SETCELL
pop af ; <-- lvl 1 pop af ; <-- lvl 1
pop hl pop hl
pop de pop de
ret ret
; Call gridSetCur with C = 1.
gridSetCurH:
push bc
ld c, 1
call gridSetCur
pop bc
ret
; Call gridSetCur with C = 0.
gridSetCurL:
push bc
ld c, 0
call gridSetCur
pop bc
ret
; Clear character under cursor ; Clear character under cursor
gridClrCur: gridClrCur:
push af push af
ld a, ' ' ld a, ' '
call gridSetCur call gridSetCurL
pop af pop af
ret ret
@ -150,19 +183,10 @@ gridLF:
push de push de
push af push af
ld a, (GRID_CURY) ld a, (GRID_CURY)
call .incA ; increase A
ld d, a
call gridClrRow
ld (GRID_CURY), a
xor a
ld (GRID_CURX), a
pop af
pop de
ret
.incA:
inc a inc a
cp GRID_ROWS cp GRID_ROWS
ret nz ; no rollover jr nz, .noscroll
; bottom reached, stay on last line and scroll screen ; bottom reached, stay on last line and scroll screen
push hl push hl
push de push de
@ -171,11 +195,21 @@ gridLF:
ld hl, GRID_BUF+GRID_COLS ld hl, GRID_BUF+GRID_COLS
ld bc, GRID_SIZE-GRID_COLS ld bc, GRID_SIZE-GRID_COLS
ldir ldir
ld hl, GRID_SCROLLED
inc (hl) ; mark as scrolled
pop bc pop bc
pop de pop de
pop hl pop hl
call gridPushScr
dec a dec a
.noscroll:
; A has been increased properly
ld d, a
call gridClrRow
ld (GRID_CURY), a
xor a
ld (GRID_CURX), a
pop af
pop de
ret ret
gridBS: gridBS:
@ -210,7 +244,7 @@ gridPutC:
cp ' ' cp ' '
ret c ; ignore unhandled control characters ret c ; ignore unhandled control characters
call gridSetCur call gridSetCurL
push af ; --> lvl 1 push af ; --> lvl 1
; Move cursor ; Move cursor
ld a, (GRID_CURX) ld a, (GRID_CURX)
@ -226,3 +260,16 @@ gridPutC:
call gridLF call gridLF
pop af ; <-- lvl 1 pop af ; <-- lvl 1
ret ret
gridGetC:
ld a, (GRID_SCROLLED)
or a
jr z, .nopush
; We've scrolled recently, update screen
xor a
ld (GRID_SCROLLED), a
call gridPushScr
.nopush:
ld a, ' '
call gridSetCurH
jp GRID_GETC

View File

@ -181,7 +181,7 @@ padGetC:
; no action button pressed, but because our pad status changed, update ; no action button pressed, but because our pad status changed, update
; VDP before looping. ; VDP before looping.
ld a, (PAD_SELCHR) ld a, (PAD_SELCHR)
call gridSetCur call gridSetCurH
jp padGetC jp padGetC
.return: .return:
ld a, LF ld a, LF
@ -190,7 +190,7 @@ padGetC:
.advance: .advance:
ld a, (PAD_SELCHR) ld a, (PAD_SELCHR)
; Z was already set from previous BIT instruction ; Z was already set from previous BIT instruction
ret jp gridSetCurL
.backspace: .backspace:
ld a, BS ld a, BS
; Z was already set from previous BIT instruction ; Z was already set from previous BIT instruction

View File

@ -23,8 +23,8 @@
; *** Code *** ; *** Code ***
vdpInit: vdpInit:
ld hl, vdpInitData ld hl, .initData
ld b, vdpInitDataEnd-vdpInitData ld b, .initDataEnd-.initData
ld c, VDP_CTLPORT ld c, VDP_CTLPORT
otir otir
@ -47,10 +47,10 @@ vdpInit:
out (VDP_CTLPORT), a out (VDP_CTLPORT), a
ld a, 0xc0 ld a, 0xc0
out (VDP_CTLPORT), a out (VDP_CTLPORT), a
xor a ; palette 0: black ld hl, .paletteData
out (VDP_DATAPORT), a ld b, .paletteDataEnd-.paletteData
ld a, 0x3f ; palette 1: white ld c, VDP_DATAPORT
out (VDP_DATAPORT), a otir
; Define tiles ; Define tiles
xor a xor a
@ -97,6 +97,28 @@ vdpInit:
out (VDP_CTLPORT), a out (VDP_CTLPORT), a
ret ret
; VDP initialisation data
.initData:
; 0x8x == set register X
.db 0b00000100, 0x80 ; Bit 2: Select mode 4
.db 0b00000000, 0x81
.db 0b11111111, 0x82 ; Name table: 0x3800
.db 0b11111111, 0x85 ; Sprite table: 0x3f00
.db 0b11111111, 0x86 ; sprite use tiles from 0x2000
.db 0b11111111, 0x87 ; Border uses palette 0xf
.db 0b00000000, 0x88 ; BG X scroll
.db 0b00000000, 0x89 ; BG Y scroll
.db 0b11111111, 0x8a ; Line counter (why have this?)
.initDataEnd:
.paletteData:
; BG palette
.db 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
; Sprite palette (inverted colors)
.db 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.paletteDataEnd:
; Convert ASCII char in A into a tile index corresponding to that character. ; Convert ASCII char in A into a tile index corresponding to that character.
; When a character is unknown, returns 0x5e (a '~' char). ; When a character is unknown, returns 0x5e (a '~' char).
vdpConv: vdpConv:
@ -108,7 +130,8 @@ vdpConv:
ld a, 0x5e ld a, 0x5e
ret ret
; grid routine. Sets cell at row D and column E to character A ; grid routine. Sets cell at row D and column E to character A. If C is one, we
; use the sprite palette.
vdpSetCell: vdpSetCell:
call vdpConv call vdpConv
; store A away ; store A away
@ -141,18 +164,11 @@ vdpSetCell:
; We're ready to send our data now. Let's go ; We're ready to send our data now. Let's go
ex af, af' ex af, af'
out (VDP_DATAPORT), a out (VDP_DATAPORT), a
; Palette select is on bit 3 of MSB
ld a, 1
and c
rla \ rla \ rla
out (VDP_DATAPORT), a
ret ret
; VDP initialisation data
vdpInitData:
; 0x8x == set register X
.db 0b00000100, 0x80 ; Bit 2: Select mode 4
.db 0b00000000, 0x81
.db 0b11111111, 0x82 ; Name table: 0x3800
.db 0b11111111, 0x85 ; Sprite table: 0x3f00
.db 0b11111111, 0x86 ; sprite use tiles from 0x2000
.db 0b11111111, 0x87 ; Border uses palette 0xf
.db 0b00000000, 0x88 ; BG X scroll
.db 0b00000000, 0x89 ; BG Y scroll
.db 0b11111111, 0x8a ; Line counter (why have this?)
vdpInitDataEnd:

View File

@ -1,7 +1,9 @@
; vid - TRS-80's video ; vid - TRS-80's video
; ;
; Implement PutC using TRS-80's SVC calls so that character it put on video ; Implement PutC and GRID_SETCELL using TRS-80's SVC calls.
; display.
.equ TRS80_COLS 80
.equ TRS80_ROWS 24
trs80PutC: trs80PutC:
push af push af
@ -14,3 +16,44 @@ trs80PutC:
pop bc pop bc
pop af pop af
ret ret
trs80SetCell:
push af
push bc
push hl ; HL altered by @VDCTL
push de ; DE altered by @VDCTL
ex de, hl
bit 0, c
ld c, a ; save A now
jr z, .skip ; Z from BIT above. cursor not set
; set cursor
ld a, 0x0f ; @VDCTL
ld b, 3 ; move cursor fn
rst 0x28
; HL altered.
; Our Row/Col is our currently-pushed DE value. Let's take advantage of
; that.
pop hl \ push hl ; HL altered. bring back from stack
.skip:
ld a, 0x0f ; @VDCTL
ld b, 2 ; display char
rst 0x28
pop de
pop hl
pop bc
pop af
ret
; This is a much faster version of gridPushScr. Use it in your glue code, but
; you need to set HL to GRID_BUF first.
trs80PushScr:
push af
push bc
ld a, 0x0f ; @VDCTL
ld b, 5 ; move from RAM to vid
; HL is already set by caller
rst 0x28
pop bc
pop af
cp a ; ensure Z
ret

View File

@ -21,6 +21,7 @@
jp fsOpen jp fsOpen
jp fsGetB jp fsGetB
jp printstr jp printstr
jp printcrlf
jp _blkGetB jp _blkGetB
jp _blkPutB jp _blkPutB
jp _blkSeek jp _blkSeek
@ -28,12 +29,15 @@
jp sdcGetB jp sdcGetB
jp sdcPutB jp sdcPutB
jp blkGetB jp blkGetB
jp stdioPutC
; interrupt hook ; interrupt hook
.fill 0x38-$ .fill 0x38-$
jp aciaInt jp aciaInt
; *** cont. ***
jp stdioPutC
.inc "err.h" .inc "err.h"
.inc "ascii.h" .inc "ascii.h"
.inc "blkdev.h" .inc "blkdev.h"

View File

@ -10,6 +10,7 @@
.equ fsOpen @+3 .equ fsOpen @+3
.equ fsGetB @+3 .equ fsGetB @+3
.equ printstr @+3 .equ printstr @+3
.equ printcrlf @+3
.equ _blkGetB @+3 .equ _blkGetB @+3
.equ _blkPutB @+3 .equ _blkPutB @+3
.equ _blkSeek @+3 .equ _blkSeek @+3
@ -17,4 +18,6 @@
.equ sdcGetB @+3 .equ sdcGetB @+3
.equ sdcPutB @+3 .equ sdcPutB @+3
.equ blkGetB @+3 .equ blkGetB @+3
.equ stdioPutC @+3
; *** cont. ***
.equ stdioPutC 0x3b

View File

@ -21,10 +21,11 @@
.equ GRID_COLS VDP_COLS .equ GRID_COLS VDP_COLS
.equ GRID_ROWS VDP_ROWS .equ GRID_ROWS VDP_ROWS
.equ GRID_SETCELL vdpSetCell .equ GRID_SETCELL vdpSetCell
.equ GRID_GETC padGetC
.inc "grid.asm" .inc "grid.asm"
.equ STDIO_RAMSTART GRID_RAMEND .equ STDIO_RAMSTART GRID_RAMEND
.equ STDIO_GETC padGetC .equ STDIO_GETC gridGetC
.equ STDIO_PUTC gridPutC .equ STDIO_PUTC gridPutC
.inc "stdio.asm" .inc "stdio.asm"

View File

@ -1,11 +1,13 @@
PROGNAME = ps2ctl PROGNAME = ps2ctl
AVRDUDEMCU ?= t45 AVRDUDEMCU ?= t45
AVRDUDEARGS ?= -c usbtiny -P usb AVRDUDEARGS ?= -c usbtiny -P usb
TARGETS = $(PROGNAME).hex os.sms TARGETS = $(PROGNAME).bin os.sms
BASEDIR = ../../.. BASEDIR = ../../..
ZASM = $(BASEDIR)/emul/zasm/zasm ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps APPS = $(BASEDIR)/apps
AVRA = $(BASEDIR)/emul/zasm/avra
AVRINC = $(BASEDIR)/avr
# Rules # Rules
@ -14,14 +16,14 @@ APPS = $(BASEDIR)/apps
all: $(TARGETS) all: $(TARGETS)
@echo Done! @echo Done!
send: $(PROGNAME).hex send: $(PROGNAME).bin
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$(PROGNAME).hex avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$(PROGNAME).bin
$(PROGNAME).hex: $(PROGNAME).asm $(PROGNAME).bin: $(PROGNAME).asm
avra -o $@ $(PROGNAME).asm $(AVRA) $(AVRINC) < $(PROGNAME).asm > $@
os.sms: glue.asm os.sms: glue.asm
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@ $(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
clean: clean:
rm -f $(TARGETS) *.eep.hex *.obj os.bin rm -f $(TARGETS)

View File

@ -55,7 +55,6 @@ either the low or high bits.
* 74xx157 (multiplexer) * 74xx157 (multiplexer)
* A NOR SR-latch. I used a 4043. * A NOR SR-latch. I used a 4043.
* Proto board, wires, IC sockets, etc. * Proto board, wires, IC sockets, etc.
* [AVRA][avra]
## Historical note ## Historical note
@ -114,4 +113,3 @@ Just hook it on. I've tried it, it works.
Did you get there? Feels pretty cool huh? Did you get there? Feels pretty cool huh?
[rc2014-ps2]: ../../rc2014/ps2 [rc2014-ps2]: ../../rc2014/ps2
[avra]: https://github.com/hsoft/avra

View File

@ -23,10 +23,11 @@
.equ GRID_COLS VDP_COLS .equ GRID_COLS VDP_COLS
.equ GRID_ROWS VDP_ROWS .equ GRID_ROWS VDP_ROWS
.equ GRID_SETCELL vdpSetCell .equ GRID_SETCELL vdpSetCell
.equ GRID_GETC kbdGetC
.inc "grid.asm" .inc "grid.asm"
.equ STDIO_RAMSTART GRID_RAMEND .equ STDIO_RAMSTART GRID_RAMEND
.equ STDIO_GETC kbdGetC .equ STDIO_GETC gridGetC
.equ STDIO_PUTC gridPutC .equ STDIO_PUTC gridPutC
.inc "stdio.asm" .inc "stdio.asm"

View File

@ -1,5 +1,3 @@
.include "tn45def.inc"
; Receives keystrokes from PS/2 keyboard and send them to the '164. On the PS/2 ; Receives keystrokes from PS/2 keyboard and send them to the '164. On the PS/2
; side, it works the same way as the controller in the rc2014/ps2 recipe. ; side, it works the same way as the controller in the rc2014/ps2 recipe.
; However, in this case, what we have on the other side isn't a z80 bus, it's ; However, in this case, what we have on the other side isn't a z80 bus, it's
@ -30,17 +28,22 @@
; written. ; written.
; Z: pointer to the next scan code to push to the 595 ; Z: pointer to the next scan code to push to the 595
; ;
.inc "avr.h"
.inc "tn254585.h"
.inc "tn45.h"
; *** Constants *** ; *** Constants ***
.equ CLK = PINB2 .equ CLK 2 ; Port B
.equ DATA = PINB1 .equ DATA 1 ; Port B
.equ CP = PINB3 .equ CP 3 ; Port B
; SR-Latch's Q pin ; SR-Latch's Q pin
.equ LQ = PINB0 .equ LQ 0 ; Port B
; SR-Latch's R pin ; SR-Latch's R pin
.equ LR = PINB4 .equ LR 4 ; Port B
; init value for TCNT0 so that overflow occurs in 100us ; init value for TCNT0 so that overflow occurs in 100us
.equ TIMER_INITVAL = 0x100-100 .equ TIMER_INITVAL 0x100-100
; *** Code *** ; *** Code ***
@ -56,9 +59,9 @@ hdlINT0:
reti reti
main: main:
ldi r16, low(RAMEND) ldi r16, RAMEND&0xff
out SPL, r16 out SPL, r16
ldi r16, high(RAMEND) ldi r16, RAMEND}8
out SPH, r16 out SPH, r16
; init variables ; init variables
@ -67,23 +70,23 @@ main:
; Setup int0 ; Setup int0
; INT0, falling edge ; INT0, falling edge
ldi r16, (1<<ISC01) ldi r16, 0x02 ; ISC01
out MCUCR, r16 out MCUCR, r16
; Enable INT0 ; Enable INT0
ldi r16, (1<<INT0) ldi r16, 0x40 ; INT0
out GIMSK, r16 out GIMSK, r16
; Setup buffer ; Setup buffer
clr YH clr YH
ldi YL, low(SRAM_START) ldi YL, SRAM_START&0xff
clr ZH clr ZH
ldi ZL, low(SRAM_START) ldi ZL, SRAM_START&0xff
; Setup timer. We use the timer to clear up "processbit" registers after ; Setup timer. We use the timer to clear up "processbit" registers after
; 100us without a clock. This allows us to start the next frame in a ; 100us without a clock. This allows us to start the next frame in a
; fresh state. at 1MHZ, no prescaling is necessary. Each TCNT0 tick is ; fresh state. at 1MHZ, no prescaling is necessary. Each TCNT0 tick is
; already 1us long. ; already 1us long.
ldi r16, (1<<CS00) ; no prescaler ldi r16, 0x01 ; CS00 - no prescaler
out TCCR0B, r16 out TCCR0B, r16
; init DDRB ; init DDRB
@ -101,7 +104,7 @@ loop:
; nothing to do. Before looping, let's check if our communication timer ; nothing to do. Before looping, let's check if our communication timer
; overflowed. ; overflowed.
in r16, TIFR in r16, TIFR
sbrc r16, TOV0 sbrc r16, 1 ; TOV0
rjmp processbitReset ; Timer0 overflow? reset processbit rjmp processbitReset ; Timer0 overflow? reset processbit
; Nothing to do for real. ; Nothing to do for real.
@ -220,7 +223,7 @@ sendTo164Loop:
resetTimer: resetTimer:
ldi r16, TIMER_INITVAL ldi r16, TIMER_INITVAL
out TCNT0, r16 out TCNT0, r16
ldi r16, (1<<TOV0) ldi r16, 0x02 ; TOV0
out TIFR, r16 out TIFR, r16
ret ret
@ -237,8 +240,8 @@ sendToPS2:
; Wait until the timer overflows ; Wait until the timer overflows
in r16, TIFR in r16, TIFR
sbrs r16, TOV0 sbrs r16, 1 ; TOV0
rjmp PC-2 rjmp $-4
; Good, 100us passed. ; Good, 100us passed.
; Pull Data low, that's our start bit. ; Pull Data low, that's our start bit.
@ -258,7 +261,7 @@ sendToPS2:
sendToPS2Loop: sendToPS2Loop:
; Wait for CLK to go low ; Wait for CLK to go low
sbic PINB, CLK sbic PINB, CLK
rjmp PC-1 rjmp $-2
; set up DATA ; set up DATA
cbi PORTB, DATA cbi PORTB, DATA
@ -268,7 +271,7 @@ sendToPS2Loop:
; Wait for CLK to go high ; Wait for CLK to go high
sbis PINB, CLK sbis PINB, CLK
rjmp PC-1 rjmp $-2
dec r16 dec r16
brne sendToPS2Loop ; not zero? loop brne sendToPS2Loop ; not zero? loop
@ -279,7 +282,7 @@ sendToPS2Loop:
; Wait for CLK to go low ; Wait for CLK to go low
sbic PINB, CLK sbic PINB, CLK
rjmp PC-1 rjmp $-2
; set parity bit ; set parity bit
cbi PORTB, DATA cbi PORTB, DATA
@ -288,22 +291,22 @@ sendToPS2Loop:
; Wait for CLK to go high ; Wait for CLK to go high
sbis PINB, CLK sbis PINB, CLK
rjmp PC-1 rjmp $-2
; Wait for CLK to go low ; Wait for CLK to go low
sbic PINB, CLK sbic PINB, CLK
rjmp PC-1 rjmp $-2
; We can now release the DATA line ; We can now release the DATA line
cbi DDRB, DATA cbi DDRB, DATA
; Wait for DATA to go low. That's our ACK ; Wait for DATA to go low. That's our ACK
sbic PINB, DATA sbic PINB, DATA
rjmp PC-1 rjmp $-2
; Wait for CLK to go low ; Wait for CLK to go low
sbic PINB, CLK sbic PINB, CLK
rjmp PC-1 rjmp $-2
; We're finished! Enable INT0, reset timer, everything back to normal! ; We're finished! Enable INT0, reset timer, everything back to normal!
rcall resetTimer rcall resetTimer
@ -314,21 +317,21 @@ sendToPS2Loop:
; Check that Y is within bounds, reset to SRAM_START if not. ; Check that Y is within bounds, reset to SRAM_START if not.
checkBoundsY: checkBoundsY:
tst YL tst YL
breq PC+2 breq $+4
ret ; not zero, nothing to do ret ; not zero, nothing to do
; YL is zero. Reset Y ; YL is zero. Reset Y
clr YH clr YH
ldi YL, low(SRAM_START) ldi YL, SRAM_START&0xff
ret ret
; Check that Z is within bounds, reset to SRAM_START if not. ; Check that Z is within bounds, reset to SRAM_START if not.
checkBoundsZ: checkBoundsZ:
tst ZL tst ZL
breq PC+2 breq $+4
ret ; not zero, nothing to do ret ; not zero, nothing to do
; ZL is zero. Reset Z ; ZL is zero. Reset Z
clr ZH clr ZH
ldi ZL, low(SRAM_START) ldi ZL, SRAM_START&0xff
ret ret
; Counts the number of 1s in r19 and set r16 to 1 if there's an even number of ; Counts the number of 1s in r19 and set r16 to 1 if there's an even number of
@ -336,10 +339,10 @@ checkBoundsZ:
checkParity: checkParity:
ldi r16, 1 ldi r16, 1
lsr r19 lsr r19
brcc PC+2 ; Carry unset? skip next brcc $+4 ; Carry unset? skip next
inc r16 ; Carry set? We had a 1 inc r16 ; Carry set? We had a 1
tst r19 ; is r19 zero yet? tst r19 ; is r19 zero yet?
brne checkParity+1 ; no? loop and skip first LDI brne checkParity+2 ; no? loop and skip first LDI
andi r16, 0x1 ; Sets Z accordingly andi r16, 0x1 ; Sets Z accordingly
ret ret

View File

@ -52,10 +52,11 @@
.equ GRID_COLS VDP_COLS .equ GRID_COLS VDP_COLS
.equ GRID_ROWS VDP_ROWS .equ GRID_ROWS VDP_ROWS
.equ GRID_SETCELL vdpSetCell .equ GRID_SETCELL vdpSetCell
.equ GRID_GETC kbdGetC
.inc "grid.asm" .inc "grid.asm"
.equ STDIO_RAMSTART GRID_RAMEND .equ STDIO_RAMSTART GRID_RAMEND
.equ STDIO_GETC kbdGetC .equ STDIO_GETC gridGetC
.equ STDIO_PUTC gridPutC .equ STDIO_PUTC gridPutC
.inc "stdio.asm" .inc "stdio.asm"

View File

@ -2,17 +2,13 @@
.equ RAMEND 0xcfff .equ RAMEND 0xcfff
; Address of the *CL driver. Same as in recv.asm ; Address of the *CL driver. Same as in recv.asm
.equ COM_DRV_ADDR 0x0238 .equ COM_DRV_ADDR 0x0238
; in sync with user.h. Last BAS_RAMEND: 0x5705 ; in sync with user.h. Last BAS_RAMEND: 0x600b
.equ USER_CODE 0x5800 .equ USER_CODE 0x6100
; Free memory in TRSDOS starts at 0x3000 ; Free memory in TRSDOS starts at 0x3000
.org 0x3000 .org 0x3000
jp init jp init
; The TRS-80 generates a double line feed if we give it both CR and LF.
; Has to be defined before the jump table.
.equ printcrlf printcr
; *** Jump Table *** ; *** Jump Table ***
jp strncmp jp strncmp
jp upcase jp upcase
@ -45,7 +41,14 @@
.equ FLOPPY_RAMSTART RAMSTART .equ FLOPPY_RAMSTART RAMSTART
.inc "trs80/floppy.asm" .inc "trs80/floppy.asm"
.equ BLOCKDEV_RAMSTART FLOPPY_RAMEND .equ GRID_RAMSTART FLOPPY_RAMEND
.equ GRID_ROWS TRS80_ROWS
.equ GRID_COLS TRS80_COLS
.equ GRID_SETCELL trs80SetCell
.equ GRID_GETC trs80GetC
.equ gridPushScr fastPushScr
.inc "grid.asm"
.equ BLOCKDEV_RAMSTART GRID_RAMEND
.equ BLOCKDEV_COUNT 3 .equ BLOCKDEV_COUNT 3
.inc "blockdev.asm" .inc "blockdev.asm"
; List of devices ; List of devices
@ -54,8 +57,9 @@
.dw blk2GetB, blk2PutB .dw blk2GetB, blk2PutB
.equ STDIO_RAMSTART BLOCKDEV_RAMEND .equ STDIO_RAMSTART BLOCKDEV_RAMEND
.equ STDIO_GETC trs80GetC .equ STDIO_GETC gridGetC
.equ STDIO_PUTC trs80PutC .equ STDIO_PUTC gridPutC
.equ STDIO_SETCUR gridSetCurH
.inc "stdio.asm" .inc "stdio.asm"
.equ FS_RAMSTART STDIO_RAMEND .equ FS_RAMSTART STDIO_RAMEND
@ -91,6 +95,7 @@
init: init:
ld sp, RAMEND ld sp, RAMEND
call gridInit
call floppyInit call floppyInit
call fsInit call fsInit
call basInit call basInit
@ -103,13 +108,6 @@ init:
jp basStart jp basStart
printcr:
push af
ld a, CR
call STDIO_PUTC
pop af
ret
; Receive a byte from *cl and put it in A. ; Receive a byte from *cl and put it in A.
; Returns A > 0xff when receiving the last byte ; Returns A > 0xff when receiving the last byte
recvCmd: recvCmd:
@ -172,6 +170,13 @@ basFindCmdExtra:
.dw recvCmd .dw recvCmd
.db 0xff ; end of table .db 0xff ; end of table
fastPushScr:
push hl
ld hl, GRID_BUF
call trs80PushScr
pop hl
ret
; *** blkdev 1: file handle 0 *** ; *** blkdev 1: file handle 0 ***
blk1GetB: blk1GetB:

View File

@ -1,4 +1,4 @@
.org 0x5800 .org 0x6100
.equ strncmp 0x3003 .equ strncmp 0x3003
.equ upcase @+3 .equ upcase @+3
.equ findchar @+3 .equ findchar @+3

View File

@ -24,3 +24,5 @@ jmp bar
mov r6, r30 mov r6, r30
lsl r3 lsl r3
tst r12 tst r12
clr YH
clr r29

Binary file not shown.