From e63bf1cde1c0d63ca1d78238f56d35401ad3a996 Mon Sep 17 00:00:00 2001 From: Greg King Date: Sun, 23 Jun 2013 03:18:28 -0400 Subject: [PATCH] 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. --- include/mouse.h | 48 +++++++-- libsrc/c128/libref.s | 12 ++- libsrc/c128/mou/c128-inkwell.s | 190 ++++++++------------------------- libsrc/c128/mouseref.s | 23 ++++ libsrc/c128/pencalib.c | 92 ++++++++++++++++ libsrc/c64/libref.s | 12 ++- libsrc/c64/mou/c64-inkwell.s | 187 ++++++++------------------------ libsrc/c64/mouseref.s | 23 ++++ libsrc/c64/pencalib.c | 93 ++++++++++++++++ libsrc/cbm/penadjust.c | 53 +++++++++ testcode/lib/pen-test.c | 42 +++++--- 11 files changed, 460 insertions(+), 315 deletions(-) create mode 100644 libsrc/c128/mouseref.s create mode 100644 libsrc/c128/pencalib.c create mode 100644 libsrc/c64/mouseref.s create mode 100644 libsrc/c64/pencalib.c create mode 100755 libsrc/cbm/penadjust.c diff --git a/include/mouse.h b/include/mouse.h index bc90263cf..bc93f8b8c 100644 --- a/include/mouse.h +++ b/include/mouse.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2003-2011, Ullrich von Bassewitz */ +/* (C) 2003-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -101,6 +101,14 @@ struct mouse_callbacks { */ }; + + +/*****************************************************************************/ +/* Declarations */ +/*****************************************************************************/ + + + /* The default mouse callbacks */ extern const struct mouse_callbacks mouse_def_callbacks; @@ -110,6 +118,13 @@ extern const char mouse_stddrv[]; /* The address of the static standard mouse driver for a platform */ extern const void mouse_static_stddrv[]; +/* 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. +** mouse_adjuster must be set before the driver is installed. +*/ +extern void __fastcall__ (*mouse_adjuster) (unsigned char *pValue); + /*****************************************************************************/ @@ -127,10 +142,10 @@ unsigned char mouse_unload (void); unsigned char __fastcall__ mouse_install (const struct mouse_callbacks* c, void* driver); -/* Install an already loaded driver. Returns an error code. */ +/* Install an already loaded driver. Return an error code. */ unsigned char mouse_uninstall (void); -/* Uninstall the currently loaded driver. Returns an error code. */ +/* Uninstall the currently loaded driver. Return an error code. */ const char* __fastcall__ mouse_geterrormsg (unsigned char code); /* Get an error message describing the error in code. */ @@ -142,7 +157,7 @@ void mouse_hide (void); */ void mouse_show (void); -/* Show the mouse. See mouse_hide for more information. */ +/* Show the mouse. See mouse_hide() for more information. */ void __fastcall__ mouse_setbox (const struct mouse_box* box); /* Set the bounding box for the mouse pointer movement. The mouse X and Y @@ -176,14 +191,31 @@ unsigned char mouse_buttons (void); */ void __fastcall__ mouse_pos (struct mouse_pos* pos); -/* Return the current mouse position */ +/* Return the current mouse position. */ void __fastcall__ mouse_info (struct mouse_info* info); -/* Return the state of the mouse buttons and the position of the mouse */ +/* Return the state of the mouse buttons and the position of the mouse. */ unsigned char __fastcall__ mouse_ioctl (unsigned char code, void* data); -/* Call the driver specific ioctl function. NON PORTABLE! Returns an error - * code. +/* Call the driver-specific ioctl function. Return an error code. + * NON-PORTABLE! + */ + +void __fastcall__ pen_calibrate (unsigned char *XOffset); +/* Ask the user to help to calibrate a lightpen. Changes the screen! + * A pointer to this function can be put into mouse_adjuster. + */ + +void __fastcall__ pen_adjust (const char *filename); +/* Get a lightpen calibration value from a file if it exists. Otherwise, call + * pen_calibrate() to create a value; then, write it into a file, so that it + * will be available at the next time that the lightpen is used. + * Might change the screen. + * pen_adjust() is optional; if you want to use its feature, + * then it must be called before a driver is installed. + * Note: This function merely saves the file-name pointer, and sets + * the mouse_adjuster pointer. The file will be read only when a driver + * is installed, and only if that driver wants to be calibrated. */ diff --git a/libsrc/c128/libref.s b/libsrc/c128/libref.s index fb22515bd..4f65e3959 100644 --- a/libsrc/c128/libref.s +++ b/libsrc/c128/libref.s @@ -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 diff --git a/libsrc/c128/mou/c128-inkwell.s b/libsrc/c128/mou/c128-inkwell.s index c76234915..4cd009f2c 100644 --- a/libsrc/c128/mou/c128-inkwell.s +++ b/libsrc/c128/mou/c128-inkwell.s @@ -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 "c128.inc" .macpack generic - .macpack cbm ; ------------------------------------------------------------------------ ; Header. Includes jump table. @@ -25,7 +24,7 @@ HEADER: ; Library reference - .addr $0000 +LIBREF: .addr $0000 ; Jump table @@ -62,14 +61,8 @@ CMOVEY: jmp $0000 ; Move the cursor to Y co-ord. XSIZE = 40 YSIZE = 25 -SCREEN_HEIGHT = YSIZE * 8 SCREEN_WIDTH = XSIZE * 8 -SCREEN_ZONE = YSIZE / 4 * XSIZE - -SCREEN := $0400 -COLOR_RAM := $D800 - -PRIMM := $FF7D ; Print immediate +SCREEN_HEIGHT = YSIZE * 8 ;---------------------------------------------------------------------------- @@ -77,6 +70,19 @@ PRIMM := $FF7D ; Print immediate ; written with the least effort in the SETBOX and GETBOX routines; so, don't ; re-order them. +.rodata + +; Default values for below variables +; (We use ".proc" because we want to define both a label and a scope.) + +.proc DefVars + .word 0 ; XMin + .word 0 ; YMin + .word SCREEN_WIDTH - 1 ; XMax + .word SCREEN_HEIGHT - 1 ; YMax + .byte %00000000 ; Buttons +.endproc + .bss Vars: @@ -89,36 +95,21 @@ 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 +OldPenX: .res 1 ; Previous HW-counter values OldPenY: .res 1 INIT_save: .res 1 .data -; Start with an average offset. - -XOffset: .byte 48 / 2 ; Calibration offset, for X position - -.rodata +; Default Inkwell calibration. +; The first number is the width of the left border; +; the second number is the actual calibration value. -; Default values for above variables -; (We use ".proc" because we want to define both a label and a scope.) +XOffset: .byte (24 + 24) / 2 ; x-offset -.proc DefVars - .word 0 ; XMin - .word 0 ; YMin - .word SCREEN_WIDTH - 1 ; XMax - .word SCREEN_HEIGHT - 1 ; YMax - .byte %00000000 ; Buttons -.endproc - -.proc Command1 - scrcode "Adjust by clicking on line." -.endproc -.proc Command2 - scrcode "Finish by clicking off box." -.endproc +; Jump to a function that puts a new calibration value into XOffset. +Calibrate: jmp $0000 .code @@ -138,15 +129,8 @@ INSTALL: lda #%11000000 sta INIT_STATUS - bit MODE - bpl @L7 ; Already 40 columns - jsr PRIMM - .byte $1B, 'x' ; Toggle the screen-width mode - .byte $0E, $00 ; Switch to lower-case chars. - ; Initiate variables. Just copy the default stuff over. -@L7: sei ldx #.sizeof (DefVars) - 1 @L0: lda DefVars,x sta Vars,x @@ -157,121 +141,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. - - lda VIC_BG_COLOR0 - ldx #6 ; Blue screen - stx VIC_BG_COLOR0 - pha - jsr CLRSCR - - 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. +; Call a calibration function through the library-reference. - 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. + 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 + jsr Calibrate + +; 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. @@ -504,11 +404,11 @@ 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. ; Therefore, the VIC-II number is doubled. Then, it points to every other pixel; ; but, it can reach across the screen. @@ -517,7 +417,7 @@ IRQ: tay ; Remember low byte lda #>0 rol a - tax + tax ; Remember high byte ; Limit the X co-ordinate to the bounding box. diff --git a/libsrc/c128/mouseref.s b/libsrc/c128/mouseref.s new file mode 100644 index 000000000..fb83c439f --- /dev/null +++ b/libsrc/c128/mouseref.s @@ -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 diff --git a/libsrc/c128/pencalib.c b/libsrc/c128/pencalib.c new file mode 100644 index 000000000..cf9a3f92b --- /dev/null +++ b/libsrc/c128/pencalib.c @@ -0,0 +1,92 @@ +/* +** Calibrate lightpen drivers to the current video hardware. +** +** 2013-06-17, Greg King +** +*/ + + +#include +#include + + +#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); + + /* Print instructions. */ + + revers (0); + 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 (); +} diff --git a/libsrc/c64/libref.s b/libsrc/c64/libref.s index fb22515bd..4f65e3959 100644 --- a/libsrc/c64/libref.s +++ b/libsrc/c64/libref.s @@ -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 diff --git a/libsrc/c64/mou/c64-inkwell.s b/libsrc/c64/mou/c64-inkwell.s index 0f0c8a40f..367be6105 100644 --- a/libsrc/c64/mou/c64-inkwell.s +++ b/libsrc/c64/mou/c64-inkwell.s @@ -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,6 +65,19 @@ COLOR_RAM := $D800 ; written with the least effort in the SETBOX and GETBOX routines; so, don't ; re-order them. +.rodata + +; Default values for below variables +; (We use ".proc" because we want to define both a label and a scope.) + +.proc DefVars + .word 0 ; XMin + .word 0 ; YMin + .word SCREEN_WIDTH - 1 ; XMax + .word SCREEN_HEIGHT - 1 ; YMax + .byte %00000000 ; Buttons +.endproc + .bss Vars: @@ -80,37 +86,23 @@ 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 +OldPenX: .res 1 ; Previous HW-counter values OldPenY: .res 1 .data -; Start with an average offset. - -XOffset: .byte 48 / 2 ; Calibration offset, for X position - -.rodata +; Default Inkwell calibration. +; The first number is the width of the left border; +; the second number is the actual calibration value. -; Default values for above variables -; (We use ".proc" because we want to define both a label and a scope.) +XOffset: .byte (24 + 24) / 2 ; x-offset -.proc DefVars - .word 0 ; XMin - .word 0 ; YMin - .word SCREEN_WIDTH - 1 ; XMax - .word SCREEN_HEIGHT - 1 ; YMax - .byte %00000000 ; Buttons -.endproc - -.proc Command1 - scrcode "Adjust by clicking on line." -.endproc -.proc Command2 - scrcode "Finish by clicking off box." -.endproc +; 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. - - lda VIC_BG_COLOR0 - ldx #6 ; Blue screen - stx VIC_BG_COLOR0 - pha - jsr CLRSCR - - 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 +; Call a calibration function through the library-reference. -; 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. + 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 + jsr Calibrate + +; 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. diff --git a/libsrc/c64/mouseref.s b/libsrc/c64/mouseref.s new file mode 100644 index 000000000..fb83c439f --- /dev/null +++ b/libsrc/c64/mouseref.s @@ -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 diff --git a/libsrc/c64/pencalib.c b/libsrc/c64/pencalib.c new file mode 100644 index 000000000..d0e6b0ff2 --- /dev/null +++ b/libsrc/c64/pencalib.c @@ -0,0 +1,93 @@ +/* +** Calibrate lightpen drivers to the current video hardware. +** +** 2013-06-17, Greg King +** +*/ + + +#include +#include + + +#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 (); +} diff --git a/libsrc/cbm/penadjust.c b/libsrc/cbm/penadjust.c new file mode 100755 index 000000000..104c33c8d --- /dev/null +++ b/libsrc/cbm/penadjust.c @@ -0,0 +1,53 @@ +/* +** Main lightpen driver calibration functions. +** +** 2013-06-23, Greg King +*/ + + +#include +#include +#include + + +static const char *name; + + +/* Get a lightpen calibration value from a file if it exists. Otherwise, call +** pen_calibrate() to create a value; then, write it into a file, so that it +** will be available at the next time that the lightpen is used. +** Might change the screen. +*/ +static void __fastcall__ adjuster (unsigned char *XOffset) +{ + int fd = open (name, O_RDONLY); + + if (fd < 0) { + pen_calibrate (XOffset); + fd = open (name, O_WRONLY | O_CREAT | O_EXCL); + if (fd >= 0) { + (void) write (fd, XOffset, 1); + close (fd); + } + } else { + (void) read (fd, XOffset, 1); + close (fd); + } +} + + +/* pen_adjust() is optional; if you want to use its feature, +** then it must be called before a driver is installed. +** Note: This function merely saves the file-name pointer, and sets +** the mouse_adjuster pointer. The file will be read only when a driver +** is installed, and only if that driver wants to be calibrated. +*/ +void __fastcall__ pen_adjust (const char *filename) +{ + if (filename != NULL && filename[0] != '\0') { + name = filename; + mouse_adjuster = adjuster; + } else { + mouse_adjuster = pen_calibrate; + } +} diff --git a/testcode/lib/pen-test.c b/testcode/lib/pen-test.c index ed1d75a2a..aa3992635 100644 --- a/testcode/lib/pen-test.c +++ b/testcode/lib/pen-test.c @@ -2,7 +2,7 @@ ** Test program for lightpen drivers. Will work for the C64/C128. ** ** 2001-09-13, Ullrich von Bassewitz -** 2013-05-24, Greg King +** 2013-06-21, Greg King ** */ @@ -55,7 +55,7 @@ # define SPRITE0_PTR ((unsigned char *)0x07F8) #endif -/* The lightpen sprite (an arrow) */ +/* An arrow sprite */ static const unsigned char PenSprite[64] = { 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, @@ -113,9 +113,9 @@ static void DoWarning (void) static void __fastcall__ ShowState (unsigned char Jailed, unsigned char Invisible) /* Display jail and cursor states. */ { - cclearxy (0, 7, 40); + cclearxy (0, 7, 32); gotoxy (0, 7); - cprintf ("Lightpen cursor is %svisible%s.", Invisible? "in" : "", Jailed? " and jailed" : ""); + cprintf ("Pointer is %svisible%s.", Invisible? "in" : "", Jailed? " and jailed" : ""); } @@ -128,8 +128,8 @@ int main (void) unsigned char width, height; bool Invisible = false, Done = false, Jailed = false; - /* Only the VIC-II has a lightpen connection. */ #ifdef __C128__ + /* Only the VIC-IIe has a lightpen connection. */ videomode (VIDEOMODE_40x25); #endif @@ -154,10 +154,12 @@ int main (void) memcpy (SPRITE0_DATA, PenSprite, sizeof PenSprite); /* Set the VIC-II sprite pointer. */ - *SPRITE0_PTR = (unsigned) SPRITE0_DATA / sizeof SPRITE0_DATA; + *SPRITE0_PTR = ((unsigned) SPRITE0_DATA & 0x3FFF) / sizeof SPRITE0_DATA; /* Set the color of sprite 0. */ VIC.spr0_color = COLOR_BLACK; + + pen_adjust ("inkwell.dat"); #endif #if DYN_DRV @@ -179,20 +181,16 @@ int main (void) screensize (&width, &height); top: - /* Print a help line. */ clrscr (); -/* revers (1); */ - cputs (" d)ebug h)ide q)uit s)how j)ail "); -/* revers (0); */ + + /* Print a help line. */ + cputs (" d)ebug h)ide q)uit s)how j)ail"); /* Put a cross at the center of the screen. */ gotoxy (width / 2 - 3, height / 2 - 1); cprintf ("%3u,%3u\r\n%*s\xDB", width / 2 * 8 + 4, height / 2 * 8 + 4, width / 2, ""); - /* Custom driver debugging line */ - cprintf ("\n\r\n Calibration X-offset = %u", (*(unsigned char *)0x3ff) * 2); - /* Expose the arrow. */ mouse_show (); ShowState (Jailed, Invisible); @@ -206,8 +204,20 @@ top: gotoxy (0, 2); cprintf (" X = %3d\r\n", info.pos.x); cprintf (" Y = %3d\r\n", info.pos.y); - cprintf (" B1 = %c\r\n", (info.buttons & MOUSE_BTN_LEFT) ? 0x5F : '^'); - cprintf (" B2 = %c", (info.buttons & MOUSE_BTN_RIGHT) ? 0x5F : '^'); + cprintf (" B1 = %c\r\n", (info.buttons & MOUSE_BTN_LEFT) ? +#ifdef __CBM__ + 0x5F +#else + 'v' +#endif + : '^'); + cprintf (" B2 = %c", (info.buttons & MOUSE_BTN_RIGHT) ? +#ifdef __CBM__ + 0x5F +#else + 'v' +#endif + : '^'); /* Handle user input. */ if (kbhit ()) { @@ -277,6 +287,6 @@ top: #endif /* Say goodbye. */ - cputsxy (0, 16, "Goodbye!"); + cputsxy (0, height / 2 + 3, "Goodbye!"); return EXIT_SUCCESS; } -- 2.39.2