Subversion Repositories svn.mios

Rev

Rev 52 | Rev 321 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
53 tk 1
; $Id: mios_enc.inc 53 2008-01-30 22:52:41Z tk $
1 tk 2
;
3
; MIOS Rotary Encoder Handler
4
;
5
; ==========================================================================
6
;
7
;  Copyright 1998-2006 Thorsten Klose (tk@midibox.org)
8
;  Licensed for personal non-commercial use only.
9
;  All other rights reserved.
10
;
11
; ==========================================================================
12
 
13
MIOS_ENC_SPEED_SLOW		EQU	0
14
MIOS_ENC_SPEED_NORMAL		EQU	1
15
MIOS_ENC_SPEED_FAST		EQU	2
16
 
17
MIOS_ENC_MODE_NON_DETENTED	EQU	0x00
18
MIOS_ENC_MODE_DETENTED		EQU	0x80
19
MIOS_ENC_MODE_DETENTED2		EQU	0x81
20
 
21
ENC_STAT_ACT_A          EQU 0	; Current status of channel A
22
ENC_STAT_ACT_B          EQU 1	; Current status of channel B
23
ENC_STAT_LAST_A         EQU 2	; Last status of channel A
24
ENC_STAT_LAST_B         EQU 3	; Last status of channel B
25
ENC_STAT_SPEED_SLOW     EQU 4	; 1 if encoder should be increment slower
26
ENC_STAT_SPEED_FAST     EQU 5	; 1 if encoder should be increment faster
27
ENC_STAT_DECINC         EQU 6	; 1 if last action was decrement, 0 if increment
28
 
29
	;; MEMO: encoder registers are saved in:
30
	;;   MIOS_DIN_REG0_x+0 (ENCx_STAT)
31
	;;   MIOS_DIN_REG0_x+1 (ENCx_PARAMETER)
32
	;;   MIOS_DIN_REG1_x+0 (ENCx_ACCL)
33
	;;   MIOS_DIN_REG1_x+1 (ENCx_INC)
34
 
35
;; --------------------------------------------------------------------------
36
;;  FUNCTION: USER_ENC_NotifyChange
37
;;  C_DECLARATION: void ENC_NotifyChange(unsigned char encoder, char incrementer)
38
;;  DESCRIPTION: This function is called by MIOS when an encoder has been
39
;;  moved
40
;;  IN: Encoder number in WREG and MIOS_PARAMETER1
41
;;      signed incrementer value in MIOS_PARAMETER2:
42
;;       - is positive when encoder has been turned clockwise
43
;;       - is negative when encoder has been turned counter clockwise
44
;;  C_IN: Encoder number in <encoder>
45
;;      signed incrementer value in <incrementer>
46
;;       - is positive when encoder has been turned clockwise
47
;;       - is negative when encoder has been turned counter clockwise
48
;;  OUT:  -
49
;;  ISR: no
50
;; --------------------------------------------------------------------------
51
 
52
;; --------------------------------------------------------------------------
53
;;  FUNCTION: MIOS_ENC_NumberGet
54
;;  C_DECLARATION: unsigned char MIOS_ENC_NumberGet(void)
55
;;  DESCRIPTION: returns the number of encoders which have been defined in the
56
;;  encoder table
57
;;  IN:	  -
58
;;  C_IN:  -
59
;;  OUT:  number of encoders in WREG and MIOS_PARAMETER1
60
;;  C_OUT:  number of encoders
61
;;  USES: FSR1, TBLPTR
62
;; --------------------------------------------------------------------------
63
MIOS_ENC_NumberGet
64
	TABLE_ADDR MIOS_ENC_PIN_TABLE
65
	clrf	MIOS_PARAMETER1
66
MIOS_ENC_NumberGetLoop
67
	tblrd*+						; read encoder pin from table
68
	incf	TABLAT, W				; end if 0xff has been specified
69
	bz	MIOS_ENC_NumberGet_End
70
	tblrd*+						; dummy read
71
	incf	MIOS_PARAMETER1, F
72
	BRA_IFCLR MIOS_PARAMETER1, 6, ACCESS, MIOS_ENC_NumberGetLoop
73
 
74
MIOS_ENC_NumberGet_End
75
	movf	MIOS_PARAMETER1, W			; return number
76
	return
77
 
78
;; --------------------------------------------------------------------------
79
;;  FUNCTION: MIOS_ENC_Abs7bitGet
80
;;  C_DECLARATION: unsigned char MIOS_ENC_Abs7bitGet(unsigned char enc)
81
;;  DESCRIPTION: returns absolute 7-bit value of encoder
82
;;  NOTE: This function uses a spare register which is only available
83
;;  when the encoder speed is set to MIOS_ENC_SPEED_NORMAL. In all other
84
;;  speed modes (MIOS_ENC_SPEED_SLOW and MIOS_ENC_SPEED_FAST) this function
85
;;  should NOT be used, instead a dedicated handler for absolute values
86
;;  should be written in this case (see enc_example* applications)
87
;;  IN:	  encoder number in WREG
88
;;  C_IN:  encoder number in <enc>
89
;;  OUT:  absolute value in WREG and MIOS_PARAMETER1
90
;;  C_OUT: absolute value
91
;;  USES: BSR, FSR1, TBLPTR
92
;;  EXAMPLE:
93
;;
94
;;	;; get the current 7-bit value of encoder #0
95
;;	movlw	0x00
96
;;	call	MIOS_ENC_Abs7bitGet
97
;;
98
;;  C_EXAMPLE:
99
;;
100
;;	// get the current 7-bit value of encoder #0
101
;;	value = MIOS_ENC_Abs7bitGet(0);
102
;;
103
;; --------------------------------------------------------------------------
104
MIOS_ENC_Abs7bitGet
105
	rcall	MIOS_ENC_Abs7bit_PtrSet
106
	movf	INDF1, W
107
	andlw	0x7f
108
	movwf	MIOS_PARAMETER1
109
	return
110
 
111
 
112
	;; help function for MIOS_ENC_Abs7bit*
113
MIOS_ENC_Abs7bit_PtrSet
114
	rcall	MIOS_ENC_Hlp_GetDIN_REG0Ptr
115
	incf	FSR1L, F
116
	return
117
 
118
;; --------------------------------------------------------------------------
119
;;  FUNCTION: MIOS_ENC_Abs7bitSet
120
;;  C_DECLARATION: void MIOS_ENC_Abs7bitSet(unsigned char enc, unsigned char value)
121
;;  DESCRIPTION: sets the absolute 7-bit value of encoder
122
;;  NOTE: This function uses a spare register which is only available
123
;;  when the encoder speed is set to MIOS_ENC_SPEED_NORMAL. In all other
124
;;  speed modes (MIOS_ENC_SPEED_SLOW and MIOS_ENC_SPEED_FAST) this function
125
;;  should NOT be used, instead a dedicated handler for absolute values
126
;;  should be written in this case (see enc_example* applications)
127
;;  IN:	  encoder number in WREG, absolute value in MIOS_PARAMETER1
128
;;  C_IN: encoder number in <enc>, absolute value in <value>
129
;;  OUT:  -
130
;;  USES: BSR, FSR1, TBLPTR
131
;;  EXAMPLE:
132
;;
133
;;	;; set the 7-bit value of encoder #0 to 0x40
134
;;	movlw	0x40			; store value in MIOS_PARAMETER1
135
;;	movwf	MIOS_PARAMETER1
136
;;	movlw	0x00			; set this value for encoder #0
137
;;	call	MIOS_ENC_Abs7bitSet
138
;;
139
;;  C_EXAMPLE:
140
;;
141
;;	// set the 7-bit value of encoder #0 to 0x40
142
;;	MIOS_ENC_Abs7bitSet(0, 0x40);
143
;;
144
;; --------------------------------------------------------------------------
145
MIOS_ENC_Abs7bitSet
146
	rcall	MIOS_ENC_Abs7bit_PtrSet
147
	movf	MIOS_PARAMETER1, W
148
	movwf	INDF1
149
	return
150
 
151
;; --------------------------------------------------------------------------
152
;;  FUNCTION: MIOS_ENC_Abs7bitAdd
153
;;  C_DECLARATION: void MIOS_ENC_Abs7bitAdd(unsigned char enc, unsigned char value)
154
;;  DESCRIPTION: adds the incrementer to the absolute 7-bit value of encoder<BR>
155
;;  This function saturates the value. That means: if the resulting value
156
;;  is greater than 127, it will be saturated to 127. The same will be done
157
;;  when the value is less than 0
158
;;  NOTE: This function uses a spare register which is only available
159
;;  when the encoder speed is set to MIOS_ENC_SPEED_NORMAL. In all other
160
;;  speed modes (MIOS_ENC_SPEED_SLOW and MIOS_ENC_SPEED_FAST) this function
161
;;  should NOT be used, instead a dedicated handler for absolute values
162
;;  should be written in this case (see enc_example* applications)
163
;;  IN:   encoder number in WREG,
164
;;	  incrementer value in MIOS_PARAMETER1
165
;;  C_IN: encoder number in <enc>
166
;;	  incrementer value in <value>
167
;;  OUT:  returns new absolute value in WREG and MIOS_PARAMETER1
168
;;        MIOS_PARAMETER2[0] is 1, if the value has been changed, 0 if it
169
;;           is equal to the old value
170
;;  C_OUT: returns new absolute value in MIOS_PARAMETER1
171
;;        MIOS_PARAMETER2[0] is 1, if the value has been changed, 0 if it
172
;;           is equal to the old value
173
;;  USES: BSR, FSR1, TBLPTR
174
;;  EXAMPLE:
175
;;
176
;;	;; subtract -5 from the 7-bit value of encoder #0
177
;;	movlw	-5			; store incrementer in MIOS_PARAMETER1
178
;;	movwf	MIOS_PARAMETER1
179
;;	movlw	0x00			; add this value for encoder #0
180
;;	call	MIOS_ENC_Abs7bitAdd
181
;;
182
;;  C_EXAMPLE:
183
;;
184
;;	// subtract -5 from the 7-bit value of encoder #0
185
;;	MIOS_ENC_Abs7bitAdd(0, -5);
186
;;
187
;; --------------------------------------------------------------------------
188
MIOS_ENC_Abs7bitAdd
189
	rcall	MIOS_ENC_Abs7bit_PtrSet
190
	movf	INDF1, W
191
	movwf	MIOS_PARAMETER2
192
	movf	MIOS_PARAMETER1, W
193
	addwf	INDF1, F
194
	movf	INDF1, W
195
	BRA_IFSET MIOS_PARAMETER1, 7, ACCESS, MIOS_ENC_Abs7bitAdd_Dec
196
MIOS_ENC_Abs7bitAdd_Inc
197
	btfsc	INDF1, 7
198
	movlw 0x7f
199
	rgoto	MIOS_ENC_Abs7bitAdd_Cont
200
MIOS_ENC_Abs7bitAdd_Dec
201
	btfsc	INDF1, 7
202
	movlw 0x00
203
	;; 	rgoto	MIOS_ENC_Abs7bitAdd_Cont
204
MIOS_ENC_Abs7bitAdd_Cont
205
	movwf	INDF1
206
	movwf	MIOS_PARAMETER1
207
	cpfseq	MIOS_PARAMETER2, ACCESS
208
	rgoto MIOS_ENC_Abs7bitAdd_EndC
209
MIOS_ENC_Abs7bitAdd_EndUC
210
	clrf	MIOS_PARAMETER2
211
	rgoto	MIOS_ENC_Abs7bitAdd_End
212
MIOS_ENC_Abs7bitAdd_EndC
213
	clrf	MIOS_PARAMETER2
214
	bsf	MIOS_PARAMETER2, 0
215
MIOS_ENC_Abs7bitAdd_End
216
	movf	MIOS_PARAMETER1, W	; return absolute value
217
	return
218
 
219
;; --------------------------------------------------------------------------
220
;;  FUNCTION: MIOS_ENC_SpeedGet
221
;;  C_DECLARATION: unsigned char MIOS_ENC_SpeedGet(unsigned char enc)
222
;;  DESCRIPTION: returns the speed setting for an encoder<BR>
223
;;  following settings are available:<BR>
224
;;     MIOS_ENC_SPEED_SLOW    0x00<BR>
225
;;     MIOS_ENC_SPEED_NORMAL  0x01<BR>
226
;;     MIOS_ENC_SPEED_FAST    0x02<BR>
227
;;  IN:	  encoder number in WREG
228
;;  C_IN: encoder number in <enc>
229
;;  OUT:  speed mode in WREG and MIOS_PARAMETER1
230
;;        speed parameter in MIOS_PARAMETER2
231
;;  C_OUT:  returns speed mode
232
;;        speed parameter in MIOS_PARAMETER2
233
;;  USES: BSR, FSR1, TBLPTR
234
;;  EXAMPLE:
235
;;
236
;;	;; return the speed setting of encoder #0
237
;;	movlw	0x00
238
;;	call	MIOS_ENC_SpeedGet
239
;;
240
;;  C_EXAMPLE:
241
;;
242
;;	// return the speed setting of encoder #0
243
;;	speed = MIOS_ENC_SpeedGet(0);
244
;;
245
;; --------------------------------------------------------------------------
246
MIOS_ENC_SpeedGet
247
	rcall	MIOS_ENC_Hlp_GetDIN_REG0Ptr
248
	movlw	MIOS_ENC_SPEED_NORMAL
249
	btfsc	INDF1, ENC_STAT_SPEED_FAST
250
	movlw MIOS_ENC_SPEED_FAST
251
	btfsc	INDF1, ENC_STAT_SPEED_SLOW
252
	movlw MIOS_ENC_SPEED_SLOW
253
	movwf	MIOS_PARAMETER1
254
	andlw	0xff		; update STATUS
255
	movff	PREINC1, MIOS_PARAMETER2
256
	return
257
 
258
 
259
 
260
;; --------------------------------------------------------------------------
261
;;  FUNCTION: MIOS_ENC_SpeedSet
262
;;  C_DECLARATION: void MIOS_ENC_SpeedSet(unsigned char enc, unsigned char mode, unsigned char parameter)
263
;;  DESCRIPTION: sets the speed for an encoder<BR>
264
;;  following settings are available:<BR>
265
;;     MIOS_ENC_SPEED_SLOW    0x00   (requires additional parameter)<BR>
266
;;     MIOS_ENC_SPEED_NORMAL  0x01   (no additional parameter)<BR>
267
;;     MIOS_ENC_SPEED_FAST    0x02   (requires additional parameter)<BR>
268
;;  NOTE: When using MIOS_ENC_SPEED_SLOW or MIOS_ENC_SPEED_FAST, the
269
;;  MIOS_ENC_Abs* functions are not available since these speed modes
270
;;  allocate a spare register which is normaly used to store the absolute value.
271
;;  So, in this case a dedicated handler for absolute values should be
272
;;  written (see enc_example* applications)
273
;;  IN:	  encoder number in WREG,
274
;;        speed mode in MIOS_PARAMETER1
275
;;        speed parameter in MIOS_PARAMETER2
276
;;  C_IN:  encoder number in <enc>
277
;;        speed mode in <mode>
278
;;        speed parameter in <parameter>
279
;;  OUT:  -
280
;;  USES: BSR, FSR1, TBLPTR
281
;;  EXAMPLE:
282
;;
283
;;  MIOS_ENC_SPEED_NORMAL
284
;;  ~~~~~~~~~~~~~~~~~~~~~
285
;;	;; this speed mode requires no additional parameter
286
;;
287
;;	;; set speed of encoder #0 to "normal"
288
;;	movlw	MIOS_ENC_SPEED_NORMAL	; normal speed mode
289
;;	movwf	MIOS_PARAMETER1
290
;;	movlw	0x00			; rotary encoder #0
291
;;	call	MIOS_ENC_SpeedSet
292
;;
293
;;  MIOS_ENC_SPEED_SLOW
294
;;  ~~~~~~~~~~~~~~~~~~~
295
;;	;; this speed mode allows to define a predivider value
296
;;	;; from 0 to 7 which has to be specified in
297
;;	;; MIOS_PARAMETER2
298
;;
299
;;	;; set speed for encoder #0 to "slow", use a predivider
300
;;	;; of 3 so that the encoder will increment every 4th
301
;;	;; step
302
;;	movlw	0x03			; predivider value (- 1)
303
;;	movwf	MIOS_PARAMETER2
304
;;	movlw	MIOS_ENC_SPEED_SLOW	; slow speed mode
305
;;	movwf	MIOS_PARAMETER1
306
;;	movlw	0x00			; rotary encoder #0
307
;;	call	MIOS_ENC_SpeedSet
308
;;
309
;;  MIOS_ENC_SPEED_FAST
310
;;  ~~~~~~~~~~~~~~~~~~~
311
;;	;; in this speed mode the increment value depends on the
312
;;	;; rotational speed based on the following formula:
313
;;
314
;;	;;    speed_ctr: decremented with every update cycle
315
;;	;;    (-> MIOS_SRIO_UpdateFrqSet)
316
;;	;;		 (normaly 1 ms) to measure the time between
317
;;	;;		 two encoder steps
318
;;	;;		 Init value: 0x7f
319
;;	;;		 reaches 0x00 after 127 update cycles
320
;;	;;		(normaly after 127 ms)
321
;;	;;    MIOS_PARAMETER2: specified with the MIOS_ENC_SpeedSet
322
;;	;;
323
;;	;;		       function, allowed values:
324
;;	;;			  0 (fast)     -> divider = 2^(7-0) = 128
325
;;	;;			  1 (faster)   -> divider = 2^(7-1) =  64
326
;;	;;			  ...
327
;;	;;			  7 (fastest)  -> divider = 2^(7-7) =	1
328
;;	;; ->
329
;;	;;    incrementer = speed_ctr / (2^(7-MIOS_PARAMETER2))
330
;;
331
;;	;; set speed for encoder #0 to "fast", speed exponent value is 2
332
;;	movlw	0x02			; speed exponent
333
;;	movwf	MIOS_PARAMETER2
334
;;	movlw	MIOS_ENC_SPEED_FAST	; fast speed mode
335
;;	movwf	MIOS_PARAMETER1
336
;;	movlw	0x00			; rotary encoder #0
337
;;	call	MIOS_ENC_SpeedSet
338
;;
339
;;  C_EXAMPLE:
340
;;
341
;;  MIOS_ENC_SPEED_NORMAL
342
;;  ~~~~~~~~~~~~~~~~~~~~~
343
;;	// this speed mode requires no additional parameter (should be zero)
344
;;
345
;;	// set speed of encoder #0 to "normal"
346
;;	MIOS_ENC_SpeedSet(0, MIOS_ENC_SPEED_NORMAL, 0);
347
;;
348
;;  MIOS_ENC_SPEED_SLOW
349
;;  ~~~~~~~~~~~~~~~~~~~
350
;;	// this speed mode allows to define a predivider value
351
;;	// from 0 to 7
352
;;
353
;;	// set speed for encoder #0 to "slow", use a predivider
354
;;	// of 3 so that the encoder will increment every 4th
355
;;	// step (predivider value (- 1))
356
;;	MIOS_ENC_SpeedSet(0, MIOS_ENC_SPEED_SLOW, 3);
357
;;
358
;;  MIOS_ENC_SPEED_FAST
359
;;  ~~~~~~~~~~~~~~~~~~~
360
;;	// in this speed mode the increment value depends on the
361
;;	// rotational speed based on the following formula:
362
;;
363
;;	//    speed_ctr: decremented with every update cycle
364
;;	//    (-> MIOS_SRIO_UpdateFrqSet)
365
;;	//		 (normaly 1 ms) to measure the time between
366
;;	//		 two encoder steps
367
;;	//		 Init value: 0x7f
368
;;	//		 reaches 0x00 after 127 update cycles
369
;;	//		(normaly after 127 ms)
370
;;	//    <parameter>: specified with the MIOS_ENC_SpeedSet
371
;;	//
372
;;	//		       function, allowed values:
373
;;	//			  0 (fast)     -> divider = 2^(7-0) = 128
374
;;	//			  1 (faster)   -> divider = 2^(7-1) =  64
375
;;	//			  ...
376
;;	//			  7 (fastest)  -> divider = 2^(7-7) =	1
377
;;	// ->
378
;;	//    incrementer = speed_ctr / (2^(7-parameter))
379
;;
380
;;	// set speed for encoder #0 to "fast", speed exponent value is 2
381
;;	MIOS_ENC_SpeedSet(0, MIOS_ENC_SPEED_FAST, 2);
382
;;
383
;; --------------------------------------------------------------------------
384
MIOS_ENC_SpeedSet
385
	rcall	MIOS_ENC_Hlp_GetDIN_REG0Ptr
386
	BRA_IFSET MIOS_PARAMETER1, 1, ACCESS, MIOS_ENC_SpeedSet_2
387
	BRA_IFSET MIOS_PARAMETER1, 0, ACCESS, MIOS_ENC_SpeedSet_1
388
MIOS_ENC_SpeedSet_0
389
	bsf	INDF1, ENC_STAT_SPEED_SLOW
390
	bcf	INDF1, ENC_STAT_SPEED_FAST
391
	rgoto	MIOS_ENC_SpeedSet_Parameter
392
MIOS_ENC_SpeedSet_1
393
	bcf	INDF1, ENC_STAT_SPEED_SLOW
394
	bcf	INDF1, ENC_STAT_SPEED_FAST
395
	return
396
MIOS_ENC_SpeedSet_2
397
	bcf	INDF1, ENC_STAT_SPEED_SLOW
398
	bsf	INDF1, ENC_STAT_SPEED_FAST
399
	;; 	rgoto	MIOS_ENC_SpeedSet_Parameter
400
MIOS_ENC_SpeedSet_Parameter
401
	movff	MIOS_PARAMETER2, PREINC1
402
	return
403
 
404
	;; help function, returns pointer to MIOS_DIN_REG0_00 register
405
MIOS_ENC_Hlp_GetDIN_REG0Ptr
406
	clrc
407
	rlf	WREG, W
408
	andlw	0x7e
409
	movwf	FSR1L
410
	TABLE_ADDR MIOS_ENC_PIN_TABLE
411
	movf	FSR1L, W
412
	TABLE_ADD_W
413
	tblrd*+
414
 
415
	lfsr	FSR1, MIOS_DIN_REG0_00
416
	movf	TABLAT, W
417
	addwf	FSR1L, F
418
	return
419
 
420
;; --------------------------------------------------------------------------
421
;;  MIOS Encoders Handler: Get the status of rotary encoders,
422
;;  save it in ENCx_STAT Bit 0 and 1
423
;; --------------------------------------------------------------------------
424
MIOS_ENC_Tick
425
	;; speedup measure: if no DIN pin change, only decrement ENCx_ACCL and do nothing else!
426
	lfsr	FSR2, MIOS_SR_DIN_CHANGED_0
427
	TABLE_ADDR MIOS_ENC_PIN_TABLE
428
	clrf	IRQ_TMP1
429
MIOS_ENC_Tick_ShortCutChkLoop
430
	movf	POSTINC2, W
431
	iorwf	IRQ_TMP1, F
432
	movf	FSR2L, W
433
	andlw	0x0f
434
	bnz	MIOS_ENC_Tick_ShortCutChkLoop
435
 
436
	;; branch to common encoder loop if any "change" flag is set
437
	movf	IRQ_TMP1, W
438
	bnz	MIOS_ENC_LoopStart
439
 
440
	SET_BSR	MIOS_IRQ_TMP_CTR
441
	clrf	MIOS_IRQ_TMP_CTR, BANKED
442
MIOS_ENC_Tick_ShortCutLoop
443
	tblrd*+					; read encoder pin from table
444
	incf	TABLAT, W			; end if 0xff has been specified
445
	bz	MIOS_ENC_Tick_End
446
 
447
	lfsr	FSR2, MIOS_DIN_REG0_00		; select ENCx_ACCL
448
	movf	TABLAT, W
449
	movwf	FSR2L
450
	bsf	FSR2L, 7
451
	movf	INDF2, W			; check if ENCx_ACCL zero
452
	skpz
453
	decf	INDF2, F			; decrement if not zero
454
 
455
	tblrd*+					; switch to next entry
456
	incf	MIOS_IRQ_TMP_CTR, F, BANKED
457
	BRA_IFCLR MIOS_IRQ_TMP_CTR, 6, BANKED, MIOS_ENC_Tick_ShortCutLoop
458
	;; shortcut end
459
	rgoto	MIOS_ENC_Tick_End
460
 
461
 
462
 
463
	;; ----
464
	;; any DIN pin has been changed --- check all encoder entries
465
MIOS_ENC_LoopStart
466
	TABLE_ADDR MIOS_ENC_PIN_TABLE
467
	SET_BSR	MIOS_IRQ_TMP_CTR
468
	clrf	MIOS_IRQ_TMP_CTR, BANKED
469
MIOS_ENC_Loop
470
	tblrd*						; read encoder pin from table
471
	incf	TABLAT, W				; end if 0xff has been specified
472
	bz	MIOS_ENC_Loop_End
473
 
474
	;; -----------------------------------------------------
475
	;; TABLAT contains number of first pin
476
	;; copy enc registers to working registers
477
	lfsr	FSR2, MIOS_DIN_REG0_00
478
	movf	TABLAT, W
479
	movwf	FSR2L
480
	movff	INDF2, IRQ_TMP4 ; (ENCx_STAT)
481
	bsf	FSR2L, 7
482
 
483
	movf	INDF2, W			; check if ENCx_ACCL zero
484
	skpz
485
	decf	INDF2, F			; decrement if not zero
486
	movf	INDF2, W
487
	movwf	IRQ_TMP5			; save result in ENCx_ACCL
488
 
489
	;; get current status of pin A and B
490
	movf	TABLAT, W
491
	call	MIOS_DIN_2PinsGet
492
	movwf	IRQ_TMP2
493
 
494
	;; check if status has been changed, jump to Atomic Handler if true
495
	movf	IRQ_TMP4, W			; (ENCx_STAT)
496
	andlw	0x03
497
	xorwf	IRQ_TMP2, W
498
	bnz	MIOS_ENC_AtomicHandler
499
MIOS_ENC_AtomicHandler_Return
500
 
501
	;; copy working registers back to enc registers
502
	lfsr	FSR2, MIOS_DIN_REG0_00
503
	movff	TABLAT, FSR2L
504
	movff	IRQ_TMP4, INDF2			; (ENCx_STAT)
505
	bsf	FSR2L, 7
506
	movff	IRQ_TMP5, INDF2			; (ENCx_ACCL)
507
	;; -----------------------------------------------------
508
 
509
	tblrd*+						; switch to next entry
510
	tblrd*+
511
	incf	MIOS_IRQ_TMP_CTR, F, BANKED
512
	BRA_IFCLR MIOS_IRQ_TMP_CTR, 6, BANKED, MIOS_ENC_Loop
513
MIOS_ENC_Loop_End
514
MIOS_ENC_Tick_End
515
	return
516
 
517
; ==============================================================
518
 
519
MIOS_ENC_AtomicHandler
520
	;; copy bit ACT_[AB] to LAST_[AB]
521
	;; IRQ_TMP4 == ENCx_STAT
522
	bcf	IRQ_TMP4, ENC_STAT_LAST_A
523
	btfsc	IRQ_TMP4, ENC_STAT_ACT_A
524
	bsf	IRQ_TMP4, ENC_STAT_LAST_A
525
	bcf	IRQ_TMP4, ENC_STAT_LAST_B
526
	btfsc	IRQ_TMP4, ENC_STAT_ACT_B
527
	bsf	IRQ_TMP4, ENC_STAT_LAST_B
528
 
529
	;; copy new status to ACT_[AB]
530
	movlw	0xfc
531
	andwf	IRQ_TMP4, F
532
	movf	IRQ_TMP2, W
533
	iorwf	IRQ_TMP4, F
534
 
535
	;; clear CHANGED flag of encoder
536
	movf	TABLAT, W
537
	call	MIOS_DIN_ChangedSet00
538
 
539
	;; set FSR2 to ENCx_INC
540
	lfsr	FSR2, MIOS_DIN_REG1_00
541
	incf	TABLAT, W
542
	addwf	FSR2L, F
543
 
544
	;; read second byte of entry --- now TABLAT contains the encoder mode!
545
	;; MIOS_ENC_MODE_NON_DETENTED or MIOS_ENC_MODE_DETENTED[12]
546
	tblrd*+
547
	tblrd*
548
 
549
	; State Machine (own Design, the Machine from Microchip on AN519
550
        ; is too simple and doesn't work correctly!)
551
	; changed 2000-1-5: special "analyse" state which corrects the ENC direction
552
	; if encoder is rotated to fast - I should patent it ;-)
553
 
554
	;; ENC_STAT[3..0] = LB, LA, B, A
555
 
556
	;; type 0x00 - INC: 2, B, D, 4
557
	;;             DEC: 1, 7, E, 8
558
	;; type 0x80 - INC: B, 4
559
	;;             DEC: 7, 8
560
	;; type 0x81 - INC: B
561
	;;             DEC: 7
562
	;; type 0x82 - INC: 4
563
	;;             DEC: 8
564
 
565
	movf	IRQ_TMP4, W
566
	andlw	0x0f
567
	JUMPTABLE_2BYTES_UNSECURE
568
	rgoto	MIOS_ENC_Do_Nothing	; 0
569
	rgoto	MIOS_ENC_Do_Dec_ND	; 1  -  only if NON_DETENTED
570
	rgoto	MIOS_ENC_Do_Inc_ND	; 2  -  only if NON_DETENTED
571
	rgoto	MIOS_ENC_Do_Nothing	; 3
572
	rgoto	MIOS_ENC_Do_Inc_D13	; 4  -  only if NON_DETENTED, DETENTED1 or DETENTED3
573
	rgoto	MIOS_ENC_Do_Nothing	; 5
574
	rgoto	MIOS_ENC_Do_Nothing	; 6
575
	rgoto	MIOS_ENC_Do_Dec_D12	; 7  -  only if NON_DETENTED, DETENTED1 or DETENTED2
576
	rgoto	MIOS_ENC_Do_Dec_D13	; 8  -  only if NON_DETENTED, DETENTED1 or DETENTED3
577
	rgoto	MIOS_ENC_Do_Nothing	; 9
578
	rgoto	MIOS_ENC_Do_Nothing	; A
579
	rgoto	MIOS_ENC_Do_Inc_D12	; B  -  only if NON_DETENTED, DETENTED1 or DETENTED2
580
	rgoto	MIOS_ENC_Do_Nothing	; C
581
	rgoto	MIOS_ENC_Do_Inc_ND	; D  -  only if NON_DETENTED
582
	rgoto	MIOS_ENC_Do_Dec_ND	; E  -  only if NON_DETENTED
583
	rgoto	MIOS_ENC_Do_Nothing	; F
584
 
585
MIOS_ENC_Do_Return
586
	tblrd*-			; switch back to first byte of entry
587
	tblrd*
588
	rgoto	MIOS_ENC_AtomicHandler_Return
589
 
590
;; --------------------------------------------------------------------------
591
 
592
MIOS_ENC_Do_Nothing
593
	rgoto	MIOS_ENC_Do_Return
594
 
595
MIOS_ENC_Do_Inc_D13
596
	;; only if NON_DETENTED, DETENTED1 or DETENTED3
597
	BRA_IFCLR TABLAT, 7, ACCESS, MIOS_ENC_Do_Inc
598
	BRA_IFCLR TABLAT, 0, ACCESS, MIOS_ENC_Do_Inc
599
	rgoto	MIOS_ENC_Do_Nothing
600
 
601
MIOS_ENC_Do_Inc_D12
602
	;; only if NON_DETENTED, DETENTED1 or DETENTED2
603
	BRA_IFCLR TABLAT, 7, ACCESS, MIOS_ENC_Do_Inc
604
	BRA_IFCLR TABLAT, 1, ACCESS, MIOS_ENC_Do_Inc
605
	rgoto	MIOS_ENC_Do_Nothing
606
 
607
MIOS_ENC_Do_Inc_ND
608
	;; only if NON_DETENTED
609
	BRA_IFSET TABLAT, 7, ACCESS, MIOS_ENC_Do_Nothing
610
	;; 	rgoto	MIOS_ENC_Do_Inc
611
 
612
MIOS_ENC_Do_Inc
613
	;; plausibility check: when accl > 0xe0, exit if last event was a DEC
614
	movlw	0xe0
615
	cpfsgt	IRQ_TMP5, ACCESS; (ENCx_ACCL)
616
	rgoto MIOS_ENC_Do_Inc_Ok
617
	BRA_IFSET IRQ_TMP4, ENC_STAT_DECINC, ACCESS, MIOS_ENC_Do_Nothing
618
MIOS_ENC_Do_Inc_Ok
619
	bcf	IRQ_TMP4, ENC_STAT_DECINC	;; memorize INC
620
 
621
	;; branch depending on encoder mode
622
	BRA_IFSET IRQ_TMP4, ENC_STAT_SPEED_FAST, ACCESS, MIOS_ENC_Do_Inc_Fast
623
	BRA_IFSET IRQ_TMP4, ENC_STAT_SPEED_SLOW, ACCESS, MIOS_ENC_Do_Inc_Slow
624
 
625
	;; normal speed
626
MIOS_ENC_Do_Inc_Normal
627
	incf	INDF2, F		; (ENCx_INC)
628
	rgoto	MIOS_ENC_SaveState
629
 
630
	;; fast speed
631
MIOS_ENC_Do_Inc_Fast
632
	rcall	MIOS_ENC_ModifyAccelerator
633
	addwf	INDF2, F		; (ENCx_INC)
634
	rgoto	MIOS_ENC_SaveState
635
 
636
	;; slow speed
637
MIOS_ENC_Do_Inc_Slow
638
	bcf	FSR2L, 7		; switch to ENCx_PARAMETER
639
	rlf	INDF2, W		; get ENCx_PARAMETER << 1
640
	swapf	WREG, W			; swap
641
	andlw	0x0f			; mask out
642
	movwf	IRQ_TMP3		; store in IRQ_TMP3
643
	incf	IRQ_TMP3, F		; increment
644
	movf	INDF2, W		; check if max value reached
645
	andlw	0x07
646
	cpfsgt	IRQ_TMP3, ACCESS
647
	rgoto MIOS_ENC_Do_Inc_Slow_NoO
648
	clrf	IRQ_TMP3		; reset predivider
649
	bsf	FSR2L, 7		; switch to ENCx_INC
650
	incf	INDF2, F		; increment ENCx_INC
651
	bcf	FSR2L, 7		; switch to ENCx_PARAMETER
652
MIOS_ENC_Do_Inc_Slow_NoO
653
	rgoto	MIOS_ENC_Do_Inc_Slow_Cont
654
 
655
; ------------------
656
 
657
MIOS_ENC_Do_Dec_D13
658
	;; only if NON_DETENTED, DETENTED1 or DETENTED3
659
	BRA_IFCLR TABLAT, 7, ACCESS, MIOS_ENC_Do_Dec
660
	BRA_IFCLR TABLAT, 0, ACCESS, MIOS_ENC_Do_Dec
661
	rgoto	MIOS_ENC_Do_Nothing
662
 
663
MIOS_ENC_Do_Dec_D12
664
	;; only if NON_DETENTED, DETENTED1 or DETENTED2
665
	BRA_IFCLR TABLAT, 7, ACCESS, MIOS_ENC_Do_Dec
666
	BRA_IFCLR TABLAT, 1, ACCESS, MIOS_ENC_Do_Dec
667
	rgoto	MIOS_ENC_Do_Nothing
668
 
669
MIOS_ENC_Do_Dec_ND
670
	BRA_IFSET TABLAT, 7, ACCESS, MIOS_ENC_Do_Nothing
671
	;; 	rgoto	MIOS_ENC_Do_Dec
672
 
673
MIOS_ENC_Do_Dec
674
	movwf	IRQ_TMP3
675
 
676
	;; plausibility check: when accl > 0xe0, exit if last event was a DEC
677
	movlw	0xe0
678
	cpfsgt	IRQ_TMP5, ACCESS; (ENCx_ACCL)
679
	rgoto MIOS_ENC_Do_Dec_Ok
680
	BRA_IFCLR IRQ_TMP4, ENC_STAT_DECINC, ACCESS, MIOS_ENC_Do_Nothing
681
MIOS_ENC_Do_Dec_Ok
682
	bsf	IRQ_TMP4, ENC_STAT_DECINC	;; memorize DEC
683
 
684
	;; branch depending on encoder mode
685
	BRA_IFSET IRQ_TMP4, ENC_STAT_SPEED_FAST, ACCESS, MIOS_ENC_Do_Dec_Fast
686
	BRA_IFSET IRQ_TMP4, ENC_STAT_SPEED_SLOW, ACCESS, MIOS_ENC_Do_Dec_Slow
687
 
688
	;; normal speed
689
MIOS_ENC_Do_Dec_Normal
690
	decf	INDF2, F		; (ENCx_INC)
691
	rgoto	MIOS_ENC_SaveState
692
 
693
	;; fast speed
694
MIOS_ENC_Do_Dec_Fast
695
	rcall	MIOS_ENC_ModifyAccelerator
696
	subwf	INDF2, F		; (ENCx_INC)
697
	rgoto	MIOS_ENC_SaveState
698
 
699
	;; slow speed
700
MIOS_ENC_Do_Dec_Slow
701
	bcf	FSR2L, 7		; switch to ENCx_PARAMETER
702
	rlf	INDF2, W		; get ENCx_PARAMETER << 1
703
	swapf	WREG, W			; swap
704
	andlw	0x0f			; mask out
705
	movwf	IRQ_TMP3		; store in IRQ_TMP3
706
	decf	IRQ_TMP3, F		; decrement
707
	BRA_IFCLR IRQ_TMP3, 7, ACCESS, MIOS_ENC_Do_Dec_Slow_NoO
708
	movf	INDF2, W
709
	andlw	0x07
710
	movwf	IRQ_TMP3
711
	bsf	FSR2L, 7		; switch to ENCx_INC
712
	decf	INDF2, F		; decrement ENCx_INC
713
	bcf	FSR2L, 7		; switch to ENCx_PARAMETER
714
MIOS_ENC_Do_Dec_Slow_NoO
715
MIOS_ENC_Do_Inc_Slow_Cont	; (also used by the INC routine)
716
	swapf	IRQ_TMP3, F		; swap
717
	rrf	IRQ_TMP3, W		; IRQ_TMP3 >> 1
718
	andlw	0x78
719
	movwf	IRQ_TMP3		; copy back to ENCx_PARAMETER
720
	movlw	0x07
721
	andwf	INDF2, F
722
	movf	IRQ_TMP3, W
723
	iorwf	INDF2, F
724
	bsf	FSR2L, 7		; switch to ENCx_INC
725
	rgoto	MIOS_ENC_SaveState
726
 
727
; ------------------
728
 
729
MIOS_ENC_SaveState
730
	setf	IRQ_TMP5		; (ENCx_ACCL)
731
	rgoto	MIOS_ENC_Do_Return
732
 
733
;; --------------------------------------------------------------------------
734
	;; used when MIOS_ENC_SPEED_FAST is set
735
	;; determines increment/decrement value depending on accelerator counter
736
MIOS_ENC_ModifyAccelerator
737
	movff	IRQ_TMP5, IRQ_TMP3	; copy accelerator counter to IRQ_TMP3
738
	bcf	FSR2L, 7		; switch to ENCx_PARAMETER
739
	movf	INDF2, W		; get speed parameter
740
	bsf	FSR2L, 7		; switch back to ENCx_INC
741
	andlw	0x07			; branch depending on parameter
742
	JUMPTABLE_2BYTES_UNSECURE
743
	rgoto	MIOS_ENC_ModifyAccelerator0
744
	rgoto	MIOS_ENC_ModifyAccelerator1
745
	rgoto	MIOS_ENC_ModifyAccelerator2
746
	rgoto	MIOS_ENC_ModifyAccelerator3
747
	rgoto	MIOS_ENC_ModifyAccelerator4
748
	rgoto	MIOS_ENC_ModifyAccelerator5
749
	rgoto	MIOS_ENC_ModifyAccelerator6
750
	rgoto	MIOS_ENC_ModifyAccelerator7
751
MIOS_ENC_ModifyAccelerator0
752
	clrc
753
	rrf	IRQ_TMP3, F
754
MIOS_ENC_ModifyAccelerator1
755
	clrc
756
	rrf	IRQ_TMP3, F
757
MIOS_ENC_ModifyAccelerator2
758
	clrc
759
	rrf	IRQ_TMP3, F
760
MIOS_ENC_ModifyAccelerator3
761
	clrc
762
	rrf	IRQ_TMP3, F
763
MIOS_ENC_ModifyAccelerator4
764
	clrc
765
	rrf	IRQ_TMP3, F
766
MIOS_ENC_ModifyAccelerator5
767
	clrc
768
	rrf	IRQ_TMP3, F
769
MIOS_ENC_ModifyAccelerator6
770
	clrc
771
	rrf	IRQ_TMP3, F
772
MIOS_ENC_ModifyAccelerator7
773
	clrc
774
	rrf	IRQ_TMP3, W
775
	skpnz
776
	movlw	1
777
	return
778
 
779
;; ==========================================================================
780
 
781
;; --------------------------------------------------------------------------
782
;;  MIOS ENC Handler
783
;;  check changed Encoder pins, call USER_ENC_NotifyChange when rotary
784
;;  encoder has been moved
785
;; --------------------------------------------------------------------------
786
MIOS_ENC_Handler
787
	SET_BSR	MIOS_TMP_CTR
788
	clrf	MIOS_TMP_CTR, BANKED
789
 
790
	TABLE_ADDR MIOS_ENC_PIN_TABLE
791
MIOS_ENC_Handler_Loop
792
	tblrd*+						; read encoder pin from table
793
	incf	TABLAT, W				; end if 0xff has been specified
794
	bz	MIOS_ENC_Handler_Loop_End
795
 
796
	;; -----------------------------------------------------
797
	;; TABLAT contains number of first pin
798
	;; copy ENCx_INC register to working register
799
	lfsr	FSR0, MIOS_DIN_REG1_00
800
	movf	TABLAT, W
801
	andlw	0x7e
802
	addlw	1
803
	addwf	FSR0L, F
804
 
805
	;; temporary disable the IRQs
806
	IRQ_DISABLE
807
 
808
	;; process next entry if encoder incrementer is zero
809
	movf	INDF0, W
810
	bz	MIOS_ENC_Handler_Loop_Next
811
 
812
	;; clear incrementer
813
	clrf	INDF0
814
 
815
	;; enable IRQs again
816
	IRQ_ENABLE
817
 
818
	;; save incrementer in MIOS_PARAMETER2
819
	movwf	MIOS_PARAMETER2
820
 
821
	;; call hook
822
	movf	MIOS_TMP_CTR, W, BANKED
823
	movwf	MIOS_PARAMETER1
824
	CALL_IFCLR MIOS_BOX_STAT, MIOS_BOX_STAT_SUSPEND_USER, ACCESS, USER_ENC_NotifyChange
825
	SET_BSR	MIOS_TMP_CTR
826
	TABLE_ADDR MIOS_ENC_PIN_TABLE
827
	clrc
828
	rlf	MIOS_TMP_CTR, W, BANKED
829
	addlw	1
830
	TABLE_ADD_W
831
 
832
MIOS_ENC_Handler_Loop_Next
833
	IRQ_ENABLE
834
	tblrd*+			; dummy read
835
	incf	MIOS_TMP_CTR, F, BANKED
836
	BRA_IFSET MIOS_TMP_CTR, 6, BANKED, MIOS_ENC_Handler_Loop_End
837
	rgoto	MIOS_ENC_Handler_Loop
838
MIOS_ENC_Handler_Loop_End
839
	return