]> git.sur5r.net Git - cc65/blob - libsrc/atari/mou/atrtt.s
Reduced clutter in root dir.
[cc65] / libsrc / atari / mou / atrtt.s
1 ;
2 ; Mouse driver for Atari Touch Tablet
3 ;
4 ; Christian Groessler, 2014-01-05
5 ;
6
7         .include        "zeropage.inc"
8         .include        "mouse-kernel.inc"
9         .include        "atari.inc"
10
11         .macpack        generic
12         .macpack        module
13
14 ; ------------------------------------------------------------------------
15 ; Header. Includes jump table
16
17 .ifdef __ATARIXL__
18         module_header   _atrxtt_mou
19 .else
20         module_header   _atrtt_mou
21 .endif
22
23 HEADER:
24
25 ; Driver signature
26
27         .byte   $6d, $6f, $75           ; "mou"
28         .byte   MOUSE_API_VERSION       ; Mouse driver API version number
29
30 ; Library reference
31
32         .addr   $0000
33
34 ; Jump table
35
36         .addr   INSTALL
37         .addr   UNINSTALL
38         .addr   HIDE
39         .addr   SHOW
40         .addr   SETBOX
41         .addr   GETBOX
42         .addr   MOVE
43         .addr   BUTTONS
44         .addr   POS
45         .addr   INFO
46         .addr   IOCTL
47         .addr   IRQ
48
49 ; Mouse driver flags
50
51         .byte   MOUSE_FLAG_LATE_IRQ
52
53 ; Callback table, set by the kernel before INSTALL is called
54
55 CHIDE:  jmp     $0000                   ; Hide the cursor
56 CSHOW:  jmp     $0000                   ; Show the cursor
57 CPREP:  jmp     $0000                   ; Prepare to move the cursor
58 CDRAW:  jmp     $0000                   ; Draw the cursor
59 CMOVEX: jmp     $0000                   ; Move the cursor to X coord
60 CMOVEY: jmp     $0000                   ; Move the cursor to Y coord
61
62
63 ;----------------------------------------------------------------------------
64 ; Constants
65
66 SCREEN_HEIGHT   = 191
67 SCREEN_WIDTH    = 319
68
69 .enum   JOY
70         UP      = $01
71         DOWN    = $02
72         LEFT    = $04
73         RIGHT   = $08
74 .endenum
75
76 ;----------------------------------------------------------------------------
77 ; Global variables. The bounding box values are sorted so that they can be
78 ; written with the least effort in the SETBOX and GETBOX routines, so don't
79 ; reorder them.
80
81 .bss
82
83 Vars:
84 YPos:           .res    2               ; Current mouse position, Y
85 XPos:           .res    2               ; Current mouse position, X
86 XMin:           .res    2               ; X1 value of bounding box
87 YMin:           .res    2               ; Y1 value of bounding box
88 XMax:           .res    2               ; X2 value of bounding box
89 YMax:           .res    2               ; Y2 value of bounding box
90 Buttons:        .res    1               ; Button mask
91
92 ; Default values for above variables
93
94 .rodata
95
96 ; (We use ".proc" because we want to define both a label and a scope.)
97
98 .proc   DefVars
99         .word   SCREEN_HEIGHT/2         ; YPos
100         .word   SCREEN_WIDTH/2          ; XPos
101         .word   0                       ; XMin
102         .word   0                       ; YMin
103         .word   SCREEN_WIDTH            ; XMax
104         .word   SCREEN_HEIGHT           ; YMax
105         .byte   0                       ; Buttons
106 .endproc
107
108 .code
109
110 ;----------------------------------------------------------------------------
111 ; INSTALL routine. Is called after the driver is loaded into memory. If
112 ; possible, check if the hardware is present.
113 ; Must return an MOUSE_ERR_xx code in a/x.
114
115 INSTALL:
116
117 ; Initialize variables. Just copy the default stuff over
118
119         ldx     #.sizeof(DefVars)-1
120 @L1:    lda     DefVars,x
121         sta     Vars,x
122         dex
123         bpl     @L1
124
125 ; Make sure the mouse cursor is at the default location.
126
127         lda     XPos
128         ldx     XPos+1
129         jsr     CMOVEX
130         lda     YPos
131         ldx     YPos+1
132         jsr     CMOVEY
133
134 ; Done, return zero (= MOUSE_ERR_OK)
135
136         ldx     #$00
137         txa
138         rts
139
140 ;----------------------------------------------------------------------------
141 ; UNINSTALL routine. Is called before the driver is removed from memory.
142 ; No return code required (the driver is removed from memory on return).
143
144 UNINSTALL       = HIDE                  ; Hide cursor on exit
145
146 ;----------------------------------------------------------------------------
147 ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages
148 ; a counter for calls to show/hide, and the driver entry point is only called
149 ; if the mouse is currently visible and should get hidden. For most drivers,
150 ; no special action is required besides hiding the mouse cursor.
151 ; No return code required.
152
153 HIDE:   php
154         sei
155         jsr     CHIDE
156         plp
157         rts
158
159 ;----------------------------------------------------------------------------
160 ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages
161 ; a counter for calls to show/hide, and the driver entry point is only called
162 ; if the mouse is currently hidden and should become visible. For most drivers,
163 ; no special action is required besides enabling the mouse cursor.
164 ; No return code required.
165
166 SHOW:   php
167         sei
168         jsr     CSHOW
169         plp
170         rts
171
172 ;----------------------------------------------------------------------------
173 ; SETBOX: Set the mouse bounding box. The parameters are passed as they come
174 ; from the C program, that is, a pointer to a mouse_box struct in a/x.
175 ; No checks are done if the mouse is currently inside the box, this is the job
176 ; of the caller. It is not necessary to validate the parameters, trust the
177 ; caller and save some code here. No return code required.
178
179 SETBOX: sta     ptr1
180         stx     ptr1+1                  ; Save data pointer
181
182         ldy     #.sizeof (MOUSE_BOX)-1
183         php
184         sei
185
186 @L1:    lda     (ptr1),y
187         sta     XMin,y
188         dey
189         bpl     @L1
190
191         plp
192         rts
193
194 ;----------------------------------------------------------------------------
195 ; GETBOX: Return the mouse bounding box. The parameters are passed as they
196 ; come from the C program, that is, a pointer to a mouse_box struct in a/x.
197
198 GETBOX: sta     ptr1
199         stx     ptr1+1                  ; Save data pointer
200
201         ldy     #.sizeof (MOUSE_BOX)-1
202         php
203         sei
204
205 @L1:    lda     XMin,y
206         sta     (ptr1),y
207         dey
208         bpl     @L1
209
210         plp
211         rts
212
213 ;----------------------------------------------------------------------------
214 ; MOVE: Move the mouse to a new position. The position is passed as it comes
215 ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will
216 ; remove the parameter from the stack on return.
217 ; No checks are done if the new position is valid (within the bounding box or
218 ; the screen). No return code required.
219 ;
220
221 MOVE:   php
222         sei                             ; No interrupts
223
224         pha
225         txa
226         pha
227         jsr     CPREP
228         pla
229         tax
230         pla
231
232         sta     YPos
233         stx     YPos+1                  ; New Y position
234         jsr     CMOVEY                  ; Set it
235
236         ldy     #$01
237         lda     (sp),y
238         sta     XPos+1
239         tax
240         dey
241         lda     (sp),y
242         sta     XPos                    ; New X position
243         jsr     CMOVEX                  ; Move the cursor
244
245         jsr     CSHOW
246
247         plp                             ; Restore interrupt flag
248         rts
249
250 ;----------------------------------------------------------------------------
251 ; BUTTONS: Return the button mask in a/x.
252
253 BUTTONS:
254         lda     Buttons
255         ldx     #$00
256         rts
257
258 ;----------------------------------------------------------------------------
259 ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
260 ; No return code required.
261
262 POS:    ldy     #MOUSE_POS::XCOORD      ; Structure offset
263
264         php
265         sei                             ; Disable interrupts
266         lda     XPos                    ; Transfer the position
267         sta     (ptr1),y
268         lda     XPos+1
269         iny
270         sta     (ptr1),y
271         lda     YPos
272         iny
273         sta     (ptr1),y
274         lda     YPos+1
275         plp                             ; Restore interrupt flag
276
277         iny
278         sta     (ptr1),y                ; Store last byte
279
280         rts                             ; Done
281
282 ;----------------------------------------------------------------------------
283 ; INFO: Returns mouse position and current button mask in the MOUSE_INFO
284 ; struct pointed to by ptr1. No return code required.
285 ;
286 ; We're cheating here to keep the code smaller: The first fields of the
287 ; mouse_info struct are identical to the mouse_pos struct, so we will just
288 ; call _mouse_pos to initialize the struct pointer and fill the position
289 ; fields.
290
291 INFO:   jsr     POS
292
293 ; Fill in the button state
294
295         lda     Buttons
296         ldy     #MOUSE_INFO::BUTTONS
297         sta     (ptr1),y
298
299         rts
300
301 ;----------------------------------------------------------------------------
302 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
303 ; specific data in ptr1, and the ioctl code in A.
304 ; Must return an error code in a/x.
305 ;
306
307 IOCTL:  lda     #<MOUSE_ERR_INV_IOCTL     ; We don't support ioclts for now
308         ldx     #>MOUSE_ERR_INV_IOCTL
309         rts
310
311 ;----------------------------------------------------------------------------
312 ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context
313 ; (so be careful). The routine MUST return carry set if the interrupt has been
314 ; 'handled' - which means that the interrupt source is gone. Otherwise it
315 ; MUST return carry clear.
316 ;
317
318 IRQ:
319
320 ; Check for a pressed button and place the result into Buttons
321
322         ldx     #0
323         stx     Buttons
324
325         lda     PORTA                   ; get other buttons
326         eor     #255
327         tax
328         and     #5                      ; pen button and left button are mapped to left mouse button
329         beq     @L01
330         lda     #MOUSE_BTN_LEFT
331         ora     Buttons
332         sta     Buttons
333 @L01:   txa
334         and     #8
335         beq     @L02
336         lda     #MOUSE_BTN_RIGHT
337         ora     Buttons
338         sta     Buttons
339
340 ; If we read 228 for X or Y positions, we assume the user has lifted the pen
341 ; and don't change the cursor position.
342
343 @L02:   lda     PADDL0
344         cmp     #228
345         beq     @Cont                   ; CF set if equal
346         lda     PADDL1
347         cmp     #228                    ; CF set if equal
348
349 @Cont:  php                             ; remember CF
350         jsr     CPREP
351         plp                             ; restore CF
352
353         bcc     @L03
354         jmp     @Show
355
356 @L03:   ldx     #0
357         stx     XPos+1
358         stx     YPos+1
359
360 ; Get cursor position
361 ; -------------------
362 ; The touch pad is read thru the paddle potentiometers. The possible
363 ; values are 1..228. Since the maximum value is less than the X
364 ; dimension we have to "stretch" this value. In order to use only
365 ; divisions by powers of two, we use the following appoximation:
366 ; 320/227 = 1.4096
367 ; 1+1/2-1/8+1/32 = 1.4062
368 ; For Y we subtract 1/8 of it to get in the YMax ballpark.
369 ; 228-228/8=199.5
370 ; A small area in the Y dimension of the touchpad isn't used with
371 ; this approximation. The Y value is inverted, (0,0) is the bottom
372 ; left corner of the touchpad.
373
374 ; X
375
376         ldx     PADDL0                  ; get X postion
377         dex                             ; decrement, since it's 1-based
378         stx     XPos
379         txa
380         lsr     a
381         tax
382         clc
383         adc     XPos
384         sta     XPos
385         bcc     @L04
386         inc     XPos+1
387 @L04:   txa
388         lsr     a                       ; port value / 4
389         lsr     a                       ; port value / 8
390         tax
391         sec
392         lda     XPos
393         stx     XPos
394         sbc     XPos
395         sta     XPos
396         bcs     @L05
397         dec     XPos+1
398 @L05:   txa
399         lsr     a                       ; port value / 16
400         lsr     a                       ; port value / 32
401         clc
402         adc     XPos
403         sta     XPos
404         bcc     @L06
405         inc     XPos+1
406
407 @L06:   tay
408         lda     XPos+1
409         tax
410
411 ; Limit the X coordinate to the bounding box
412
413         cpy     XMin
414         sbc     XMin+1
415         bpl     @L07
416         ldy     XMin
417         ldx     XMin+1
418         jmp     @L08
419 @L07:   txa
420
421         cpy     XMax
422         sbc     XMax+1
423         bmi     @L08
424         ldy     XMax
425         ldx     XMax+1
426 @L08:   sty     XPos
427         stx     XPos+1
428
429 ; Move the mouse pointer to the new X pos
430
431         tya
432         jsr     CMOVEX
433
434 ; Y
435
436         ldx     PADDL1                  ; get Y postion
437         dex                             ; decrement, since it's 1-based
438         stx     YPos
439         lda     #228
440         sec
441         sbc     YPos                    ; invert value
442         tax
443         lsr     a
444         lsr     a
445         lsr     a
446         sta     YPos
447         txa
448         sec
449         sbc     YPos
450         sta     YPos
451         tay
452         lda     YPos+1
453         tax
454
455 ; Limit the Y coordinate to the bounding box
456
457         cpy     YMin
458         sbc     YMin+1
459         bpl     @L09
460         ldy     YMin
461         ldx     YMin+1
462         jmp     @L10
463 @L09:   txa
464
465         cpy     YMax
466         sbc     YMax+1
467         bmi     @L10
468         ldy     YMax
469         ldx     YMax+1
470 @L10:   sty     YPos
471         stx     YPos+1
472
473 ; Move the mouse pointer to the new X pos
474
475         tya
476         jsr     CMOVEY
477
478 @Show:  jsr     CDRAW
479
480         clc                             ; Interrupt not "handled"
481         rts
482