]> git.sur5r.net Git - cc65/commitdiff
Used a library-reference method to calibrate lightpen drivers.
authorGreg King <gregdk@users.sf.net>
Sun, 23 Jun 2013 07:18:28 +0000 (03:18 -0400)
committerGreg King <gregdk@users.sf.net>
Sun, 23 Jun 2013 07:18:28 +0000 (03:18 -0400)
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
libsrc/c128/libref.s
libsrc/c128/mou/c128-inkwell.s
libsrc/c128/mouseref.s [new file with mode: 0644]
libsrc/c128/pencalib.c [new file with mode: 0644]
libsrc/c64/libref.s
libsrc/c64/mou/c64-inkwell.s
libsrc/c64/mouseref.s [new file with mode: 0644]
libsrc/c64/pencalib.c [new file with mode: 0644]
libsrc/cbm/penadjust.c [new file with mode: 0755]
testcode/lib/pen-test.c

index bc90263cf6c48ae11ecc612cceb18fce31c0d8e3..bc93f8b8ce99ba59d46a928c3ce287d96a9da46f 100644 (file)
@@ -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.
  */
 
 
index fb22515bd154539793bcc72b08246ae2ba1a61c0..4f65e3959c94e2bae5b0673a1ee7d5987ccdec5f 100644 (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
index c76234915aa9c1035e8a1ea8533a7c43f36e2500..4cd009f2ce79a6034b58630da89424cc8118130c 100644 (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        "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               ; Function will set this variable
+        ldx     #>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 (file)
index 0000000..fb83c43
--- /dev/null
@@ -0,0 +1,23 @@
+;\r
+; Pointer for library references by device drivers.\r
+;\r
+; 2013-06-23, Greg King\r
+;\r
+\r
+        .export         mouse_libref, _mouse_adjuster\r
+\r
+        .data\r
+\r
+mouse_libref:                   ; generic label for mouse-kernel\r
+\r
+; A program optionally can set this pointer to a function that gives\r
+; a calibration value to a driver.  If this pointer isn't NULL,\r
+; then a driver that wants a value can call that function.\r
+;\r
+; The function might read a value from a file; or, it might ask the user\r
+; to help calibrate the driver.\r
+;\r
+; void __fastcall__ (*mouse_adjuster)(unsigned char *) = NULL;\r
+;\r
+_mouse_adjuster:\r
+        .addr   $0000\r
diff --git a/libsrc/c128/pencalib.c b/libsrc/c128/pencalib.c
new file mode 100644 (file)
index 0000000..cf9a3f9
--- /dev/null
@@ -0,0 +1,92 @@
+/*\r
+** Calibrate lightpen drivers to the current video hardware.\r
+**\r
+** 2013-06-17, Greg King\r
+**\r
+*/\r
+\r
+\r
+#include <conio.h>\r
+#include <mouse.h>\r
+\r
+\r
+#define COMMAND1 "Adjust by clicking on line."\r
+#define COMMAND2 "Finish by clicking off bar."\r
+\r
+\r
+/* There is a delay between when the VIC sends its signal, and when the display\r
+** shows that signal.  There is another delay between the display and when the\r
+** lightpen says that it saw that signal.  Each display and pen is different.\r
+** Therefore, the driver must be calibrated to them.  A white bar is painted on\r
+** the screen; and, a line is drawn down the middle of it.  When the user\r
+** clicks on that line, the difference between its position and where the VIC\r
+** thinks that the pen is pointing becomes an offset that is subtracted from\r
+** what the VIC sees.\r
+*/\r
+void __fastcall__ pen_calibrate (unsigned char *XOffset)\r
+{\r
+    unsigned char oldBg = bgcolor (COLOR_BLUE);\r
+    unsigned char oldText = textcolor (COLOR_GRAY3);\r
+    unsigned char oldRev = revers (1);\r
+    unsigned char sprite0Color = VIC.spr_color[0];\r
+    unsigned char width, width2, height, height4, height8;\r
+    struct mouse_info info;\r
+\r
+    screensize (&width, &height);\r
+    width2 = width / 2;\r
+    height4 = height / 4;\r
+    height8 = height4 * 8;\r
+\r
+    /* Draw a bar and line. */\r
+\r
+    clrscr ();\r
+    cclearxy (0, height4, height4 * width);\r
+    cvlinexy (width2, height4 + 1, height4 - 2);\r
+\r
+    /* Print instructions. */\r
+\r
+    revers (0);\r
+    cputsxy (width2 - (sizeof COMMAND1) / 2, height / 2 + 1, COMMAND1);\r
+    cputsxy (width2 - (sizeof COMMAND2) / 2, height / 2 + 3, COMMAND2);\r
+\r
+    VIC.spr_color[0] = COLOR_GRAY2;\r
+    mouse_show ();\r
+    mouse_move (width2 * 8, height8 / 2);\r
+\r
+    for (;;) {\r
+        /* Wait for the main button to be released. */\r
+\r
+        do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));\r
+\r
+        /* Wait for the main button to be pressed. */\r
+\r
+        do {\r
+            mouse_info (&info);\r
+        } while (!(info.buttons & MOUSE_BTN_LEFT));\r
+\r
+        /* Find out if the pen is on or off the bar. */\r
+\r
+        if (info.pos.y < height8 || info.pos.y >= height8 * 2) {\r
+            break;\r
+        }\r
+\r
+        /* On the bar; adjust the offset. */\r
+        /* Characters are eight pixels wide.\r
+        ** The VIC-II sees every other pixel;\r
+        ** so, we use half of the difference.\r
+        */\r
+\r
+        *XOffset += (info.pos.x - (width2 * 8 + 8/2)) / 2;\r
+    }\r
+\r
+    /* Off the bar; wait for the main button to be released. */\r
+\r
+    do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));\r
+\r
+    mouse_hide ();\r
+    VIC.spr_color[0] = sprite0Color;\r
+    revers (oldRev);\r
+    textcolor (oldText);\r
+    bgcolor (oldBg);\r
+    clrscr ();\r
+}\r
index fb22515bd154539793bcc72b08246ae2ba1a61c0..4f65e3959c94e2bae5b0673a1ee7d5987ccdec5f 100644 (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
index 0f0c8a40f4b1d16a00c681e5c8760061208d367f..367be6105cf5010219865203620d43257b6ad622 100644 (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,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               ; Function will set this variable
+        ldx     #>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 (file)
index 0000000..fb83c43
--- /dev/null
@@ -0,0 +1,23 @@
+;\r
+; Pointer for library references by device drivers.\r
+;\r
+; 2013-06-23, Greg King\r
+;\r
+\r
+        .export         mouse_libref, _mouse_adjuster\r
+\r
+        .data\r
+\r
+mouse_libref:                   ; generic label for mouse-kernel\r
+\r
+; A program optionally can set this pointer to a function that gives\r
+; a calibration value to a driver.  If this pointer isn't NULL,\r
+; then a driver that wants a value can call that function.\r
+;\r
+; The function might read a value from a file; or, it might ask the user\r
+; to help calibrate the driver.\r
+;\r
+; void __fastcall__ (*mouse_adjuster)(unsigned char *) = NULL;\r
+;\r
+_mouse_adjuster:\r
+        .addr   $0000\r
diff --git a/libsrc/c64/pencalib.c b/libsrc/c64/pencalib.c
new file mode 100644 (file)
index 0000000..d0e6b0f
--- /dev/null
@@ -0,0 +1,93 @@
+/*\r
+** Calibrate lightpen drivers to the current video hardware.\r
+**\r
+** 2013-06-17, Greg King\r
+**\r
+*/\r
+\r
+\r
+#include <conio.h>\r
+#include <mouse.h>\r
+\r
+\r
+#define COMMAND1 "Adjust by clicking on line."\r
+#define COMMAND2 "Finish by clicking off bar."\r
+\r
+\r
+/*\r
+** There is a delay between when the VIC sends its signal, and when the display\r
+** shows that signal.  There is another delay between the display and when\r
+** the lightpen says that it saw that signal. Each display and pen is different.\r
+** Therefore, the driver must be calibrated to them.  A white bar is painted on\r
+** the screen; and, a line is drawn down the middle of it.  When the user clicks\r
+** on that line, the difference between its position and where the VIC thinks\r
+** that the pen is pointing becomes an offset that is subtracted from what the\r
+** VIC sees.\r
+*/\r
+void __fastcall__ pen_calibrate (unsigned char *XOffset)\r
+{\r
+    unsigned char oldBg = bgcolor (COLOR_BLUE);\r
+    unsigned char oldText = textcolor (COLOR_GRAY3);\r
+    unsigned char oldRev = revers (1);\r
+    unsigned char sprite0Color = VIC.spr_color[0];\r
+    unsigned char width, width2, height, height4, height8;\r
+    struct mouse_info info;\r
+\r
+    screensize (&width, &height);\r
+    width2 = width / 2;\r
+    height4 = height / 4;\r
+    height8 = height4 * 8;\r
+\r
+    /* Draw a bar and line. */\r
+\r
+    clrscr ();\r
+    cclearxy (0, height4, height4 * width);\r
+    cvlinexy (width2, height4 + 1, height4 - 2);\r
+    revers (0);\r
+\r
+    /* Print instructions. */\r
+\r
+    cputsxy (width2 - (sizeof COMMAND1) / 2, height / 2 + 1, COMMAND1);\r
+    cputsxy (width2 - (sizeof COMMAND2) / 2, height / 2 + 3, COMMAND2);\r
+\r
+    VIC.spr_color[0] = COLOR_GRAY2;\r
+    mouse_show ();\r
+    mouse_move (width2 * 8, height8 / 2);\r
+\r
+    for (;;) {\r
+        /* Wait for the main button to be released. */\r
+\r
+        do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));\r
+\r
+        /* Wait for the main button to be pressed. */\r
+\r
+        do {\r
+            mouse_info (&info);\r
+        } while (!(info.buttons & MOUSE_BTN_LEFT));\r
+\r
+        /* Find out if the pen is on or off the bar. */\r
+\r
+        if (info.pos.y < height8 || info.pos.y >= height8 * 2) {\r
+            break;\r
+        }\r
+\r
+        /* On the bar; adjust the offset. */\r
+        /* Characters are eight pixels wide.\r
+        ** The VIC-II sees every other pixel;\r
+        ** so, we use half of the difference.\r
+        */\r
+\r
+        *XOffset += (info.pos.x - (width2 * 8 + 8/2)) / 2;\r
+    }\r
+\r
+    /* Off the bar; wait for the main button to be released. */\r
+\r
+    do ; while ((mouse_buttons () & MOUSE_BTN_LEFT));\r
+\r
+    mouse_hide ();\r
+    VIC.spr_color[0] = sprite0Color;\r
+    revers (oldRev);\r
+    textcolor (oldText);\r
+    bgcolor (oldBg);\r
+    clrscr ();\r
+}\r
diff --git a/libsrc/cbm/penadjust.c b/libsrc/cbm/penadjust.c
new file mode 100755 (executable)
index 0000000..104c33c
--- /dev/null
@@ -0,0 +1,53 @@
+/*\r
+** Main lightpen driver calibration functions.\r
+**\r
+** 2013-06-23, Greg King\r
+*/\r
+\r
+\r
+#include <fcntl.h>\r
+#include <unistd.h>\r
+#include <mouse.h>\r
+\r
+\r
+static const char *name;\r
+\r
+\r
+/* Get a lightpen calibration value from a file if it exists.  Otherwise, call\r
+** pen_calibrate() to create a value; then, write it into a file, so that it\r
+** will be available at the next time that the lightpen is used.\r
+** Might change the screen.\r
+*/\r
+static void __fastcall__ adjuster (unsigned char *XOffset)\r
+{\r
+    int fd = open (name, O_RDONLY);\r
+\r
+    if (fd < 0) {\r
+        pen_calibrate (XOffset);\r
+        fd = open (name, O_WRONLY | O_CREAT | O_EXCL);\r
+        if (fd >= 0) {\r
+            (void) write (fd, XOffset, 1);\r
+            close (fd);\r
+        }\r
+    } else {\r
+        (void) read (fd, XOffset, 1);\r
+        close (fd);\r
+    }\r
+}\r
+\r
+\r
+/* pen_adjust() is optional; if you want to use its feature,\r
+** then it must be called before a driver is installed.\r
+** Note:  This function merely saves the file-name pointer, and sets\r
+** the mouse_adjuster pointer.  The file will be read only when a driver\r
+** is installed, and only if that driver wants to be calibrated.\r
+*/\r
+void __fastcall__ pen_adjust (const char *filename)\r
+{\r
+    if (filename != NULL && filename[0] != '\0') {\r
+        name = filename;\r
+        mouse_adjuster = adjuster;\r
+    } else {\r
+        mouse_adjuster = pen_calibrate;\r
+    }\r
+}\r
index ed1d75a2ad021280bde50a0854d33b87e6c67698..aa3992635be3f5f6bcce8ab356b85f6d04694442 100644 (file)
@@ -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;
 }