Used a library-reference method to calibrate lightpen drivers.

The mouse reference is a pointer.  If it's NULL, the driver uses a default.  If it's non-NULL, then it points to a function that the driver can call.  That function will adjust the driver's calibration value.  It could ask the user to adjust the pen; or, it could read a file that holds a value from a previous calibration.

Application writers can choose how it's done: a function that's provided by the library, a custom function, or nothing.
This commit is contained in:
Greg King
2013-06-23 03:18:28 -04:00
parent 66ca781bb1
commit e63bf1cde1
11 changed files with 463 additions and 318 deletions

View File

@@ -1,12 +1,18 @@
;
; Oliver Schmidt, 2013-05-31
; 2013-05-31, Oliver Schmidt
; 2013-06-11, Greg King
;
.export em_libref, joy_libref, mouse_libref, ser_libref, tgi_libref
.export em_libref
.export joy_libref
; .export mouse_libref
.export ser_libref
.export tgi_libref
.import _exit
em_libref := _exit
joy_libref := _exit
mouse_libref := _exit
;mouse_libref := _exit
ser_libref := _exit
tgi_libref := _exit

View File

@@ -1,7 +1,7 @@
;
; Driver for the Inkwell Systems 170-C and 184-C lightpens.
;
; 2013-06-03, Greg King
; 2013-06-17, Greg King
;
.include "zeropage.inc"
@@ -9,7 +9,6 @@
.include "c64.inc"
.macpack generic
.macpack cbm
; ------------------------------------------------------------------------
; Header. Includes jump table.
@@ -25,7 +24,7 @@ HEADER:
; Library reference
.addr $0000
LIBREF: .addr $0000
; Jump table
@@ -57,14 +56,8 @@ CMOVEY: jmp $0000 ; Move the cursor to Y co-ord.
;----------------------------------------------------------------------------
; Constants
SCREEN_HEIGHT = YSIZE * 8
SCREEN_WIDTH = XSIZE * 8
SCREEN_ZONE = YSIZE / 4 * XSIZE
; This driver is for the standard 40-column screen.
SCREEN := $0400
COLOR_RAM := $D800
SCREEN_HEIGHT = YSIZE * 8
;----------------------------------------------------------------------------
@@ -72,29 +65,9 @@ COLOR_RAM := $D800
; written with the least effort in the SETBOX and GETBOX routines; so, don't
; re-order them.
.bss
Vars:
XMin: .res 2 ; X1 value of bounding box
YMin: .res 2 ; Y1 value of bounding box
XMax: .res 2 ; X2 value of bounding box
YMax: .res 2 ; Y2 value of bounding box
Buttons: .res 1 ; Button status bits
XPos: .res 2 ; Current lightpen position, X
YPos: .res 2 ; Current lightpen position, Y
OldPenX: .res 1 ; Old HW-counter values
OldPenY: .res 1
.data
; Start with an average offset.
XOffset: .byte 48 / 2 ; Calibration offset, for X position
.rodata
; Default values for above variables
; Default values for below variables
; (We use ".proc" because we want to define both a label and a scope.)
.proc DefVars
@@ -105,12 +78,31 @@ XOffset: .byte 48 / 2 ; Calibration offset, for X position
.byte %00000000 ; Buttons
.endproc
.proc Command1
scrcode "Adjust by clicking on line."
.endproc
.proc Command2
scrcode "Finish by clicking off box."
.endproc
.bss
Vars:
XMin: .res 2 ; X1 value of bounding box
YMin: .res 2 ; Y1 value of bounding box
XMax: .res 2 ; X2 value of bounding box
YMax: .res 2 ; Y2 value of bounding box
Buttons: .res 1 ; Button status bits
XPos: .res 2 ; Current lightpen position, X
YPos: .res 2 ; Current lightpen position, Y
OldPenX: .res 1 ; Previous HW-counter values
OldPenY: .res 1
.data
; Default Inkwell calibration.
; The first number is the width of the left border;
; the second number is the actual calibration value.
XOffset: .byte (24 + 24) / 2 ; x-offset
; Jump to a function that puts a new calibration value into XOffset.
Calibrate: jmp $0000
.code
@@ -124,7 +116,6 @@ INSTALL:
; Initiate variables. Just copy the default stuff over.
sei
ldx #.sizeof (DefVars) - 1
@L0: lda DefVars,x
sta Vars,x
@@ -135,121 +126,37 @@ INSTALL:
ldy VIC_LPEN_Y
stx OldPenX
sty OldPenY
cli
; There is a delay between when the VIC sends its signal, and when the display
; shows that signal. There is another delay between the display and when
; the lightpen says that it saw that signal. Each display and pen is different.
; Therefore, this driver must be calibrated to them. A white box is painted on
; the screen; and, a line is drawn down the middle of it. When the user clicks
; on that line, the difference between its position and where the VIC thinks
; that the pen is pointing becomes an offset that is subtracted from what the
; VIC sees.
; Call a calibration function through the library-reference.
lda VIC_BG_COLOR0
ldx #6 ; Blue screen
stx VIC_BG_COLOR0
pha
jsr CLRSCR
lda LIBREF
ldx LIBREF+1
sta ptr1 ; Point to mouse_adjuster
stx ptr1+1
ldy #0
lda (ptr1),y
sta Calibrate+1 ; Point to function
iny
lda (ptr1),y
sta Calibrate+2
ora Calibrate+1 ; Don't call pointer if it's NULL
bze @L1
lda #<XOffset ; Function will set this variable
ldx #>XOffset
jsr Calibrate
ldy #.sizeof (Command2) - 1
@L2: lda Command2,y
sta SCREEN + SCREEN_ZONE * 2 + XSIZE * 3 + (XSIZE - .sizeof (Command2)) / 2,y
lda #15 ; Light gray text
sta COLOR_RAM + SCREEN_ZONE * 2 + XSIZE * 3 + (XSIZE - .sizeof (Command1)) / 2,y
dey
bpl @L2
ldy #.sizeof (Command1) - 1
@L1: lda Command1,y
sta SCREEN + SCREEN_ZONE * 2 + XSIZE * 1 + (XSIZE - .sizeof (Command1)) / 2,y
lda #15 ; Light gray text
sta COLOR_RAM + SCREEN_ZONE * 2 + XSIZE * 1 + (XSIZE - .sizeof (Command1)) / 2,y
dey
bpl @L1
ldx #SCREEN_ZONE
@L3: lda #$80 | $20 ; Reversed space screen-code
sta SCREEN + SCREEN_ZONE - 1,x
lda #15 ; Light gray box
sta COLOR_RAM + SCREEN_ZONE - 1,x
dex
bnz @L3
ldy #$80 | $5d ; Reversed vertical-bar screen-code
.repeat 4, L
sty SCREEN + SCREEN_ZONE + (L + 1) * XSIZE + XSIZE / 2
.endrep
lda VIC_SPR0_COLOR
ldx #12 ; Medium gray pointer
stx VIC_SPR0_COLOR
pha
jsr SHOW
lda #<(SCREEN_HEIGHT / 4 / 2)
ldx #>(SCREEN_HEIGHT / 4 / 2)
jsr PutCursor
; Wait for the main button to be released.
@L4: lda Buttons
bnz @L4
; Wait for the main button to be pressed.
@L5: lda Buttons
bze @L5
; Find out if the pen is on or off the box.
ldy YPos
ldx YPos+1
txa
cpy #<(YSIZE / 4 * 1 * 8)
sbc #>(YSIZE / 4 * 1 * 8)
bmi @L6 ; Above box
txa
cpy #<(YSIZE / 4 * 2 * 8)
sbc #>(YSIZE / 4 * 2 * 8)
bpl @L6 ; Below box
; The pen is on the box; adjust the offset.
lda OldPenX
sub #(XSIZE * 8 / 2 + 8/2) / 2
sta XOffset
sta OldPenX ; Make IRQ update X co-ordinate
jmp @L4
; Wait for the main button to be released.
@L6: lda Buttons
bnz @L6
lda XOffset ; Tell test program about calibration
sta $3ff
pla
sta VIC_SPR0_COLOR
pla
sta VIC_BG_COLOR0
jsr CLRSCR
; Be sure the lightpen cursor is invisible and at the default location.
; Be sure that the lightpen cursor is invisible and at the default location.
; It needs to be done here because the lightpen interrupt handler doesn't
; set the lightpen position if it hasn't changed.
jsr HIDE
@L1: jsr CHIDE
lda #<(SCREEN_HEIGHT / 2)
ldx #>(SCREEN_HEIGHT / 2)
PutCursor:
sei
jsr MoveY
lda #<(SCREEN_WIDTH / 2)
ldx #>(SCREEN_WIDTH / 2)
jsr MoveX
cli
; Done, return zero.
@@ -478,20 +385,20 @@ IRQ:
beq @SkipX
sta OldPenX
; Adjust the co-ordinate by the calibration offset.
; Adjust the value by the calibration offset.
sub XOffset
; Calculate the new X co-ordinate (--> .AY --> .XY).
; Calculate the new X co-ordinate.
; The VIC-II register is eight bits; but, the screen co-ordinate is nine bits.
; Therefor, the VIC-II number is doubled. Then, it points to every other pixel;
; Therefore, the VIC-II number is doubled. Then, it points to every other pixel;
; but, it can reach across the screen.
asl a
tay ; Remember low byte
lda #>0
rol a
tax
tax ; Remember high byte
; Limit the X co-ordinate to the bounding box.

23
libsrc/c64/mouseref.s Normal file
View File

@@ -0,0 +1,23 @@
;
; Pointer for library references by device drivers.
;
; 2013-06-23, Greg King
;
.export mouse_libref, _mouse_adjuster
.data
mouse_libref: ; generic label for mouse-kernel
; A program optionally can set this pointer to a function that gives
; a calibration value to a driver. If this pointer isn't NULL,
; then a driver that wants a value can call that function.
;
; The function might read a value from a file; or, it might ask the user
; to help calibrate the driver.
;
; void __fastcall__ (*mouse_adjuster)(unsigned char *) = NULL;
;
_mouse_adjuster:
.addr $0000

93
libsrc/c64/pencalib.c Normal file
View File

@@ -0,0 +1,93 @@
/*
** Calibrate lightpen drivers to the current video hardware.
**
** 2013-06-17, Greg King
**
*/
#include <conio.h>
#include <mouse.h>
#define COMMAND1 "Adjust by clicking on line."
#define COMMAND2 "Finish by clicking off bar."
/*
** There is a delay between when the VIC sends its signal, and when the display
** shows that signal. There is another delay between the display and when
** the lightpen says that it saw that signal. Each display and pen is different.
** Therefore, the driver must be calibrated to them. A white bar is painted on
** the screen; and, a line is drawn down the middle of it. When the user clicks
** on that line, the difference between its position and where the VIC thinks
** that the pen is pointing becomes an offset that is subtracted from what the
** VIC sees.
*/
void __fastcall__ pen_calibrate (unsigned char *XOffset)
{
unsigned char oldBg = bgcolor (COLOR_BLUE);
unsigned char oldText = textcolor (COLOR_GRAY3);
unsigned char oldRev = revers (1);
unsigned char sprite0Color = VIC.spr_color[0];
unsigned char width, width2, height, height4, height8;
struct mouse_info info;
screensize (&width, &height);
width2 = width / 2;
height4 = height / 4;
height8 = height4 * 8;
/* Draw a bar and line. */
clrscr ();
cclearxy (0, height4, height4 * width);
cvlinexy (width2, height4 + 1, height4 - 2);
revers (0);
/* Print instructions. */
cputsxy (width2 - (sizeof COMMAND1) / 2, height / 2 + 1, COMMAND1);
cputsxy (width2 - (sizeof COMMAND2) / 2, height / 2 + 3, COMMAND2);
VIC.spr_color[0] = COLOR_GRAY2;
mouse_show ();
mouse_move (width2 * 8, height8 / 2);
for (;;) {
/* Wait for the main button to be released. */
do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));
/* Wait for the main button to be pressed. */
do {
mouse_info (&info);
} while (!(info.buttons & MOUSE_BTN_LEFT));
/* Find out if the pen is on or off the bar. */
if (info.pos.y < height8 || info.pos.y >= height8 * 2) {
break;
}
/* On the bar; adjust the offset. */
/* Characters are eight pixels wide.
** The VIC-II sees every other pixel;
** so, we use half of the difference.
*/
*XOffset += (info.pos.x - (width2 * 8 + 8/2)) / 2;
}
/* Off the bar; wait for the main button to be released. */
do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));
mouse_hide ();
VIC.spr_color[0] = sprite0Color;
revers (oldRev);
textcolor (oldText);
bgcolor (oldBg);
clrscr ();
}