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