Subversion Repositories svn.mios

Rev

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

Rev Author Line No. Line
44 tk 1
; $Id: sid_se_l.inc 878 2010-01-02 15:40:58Z tk $
1 tk 2
;
3
; MIDIbox SID
4
; Lead Engine
5
;
6
; ==========================================================================
7
;
8
;  Copyright 1998-2007 Thorsten Klose (tk@midibox.org)
9
;  Idea for ENV Curve Parameter and OSC synchronization by Jess D. Skov-Nielsen
10
;  Licensed for personal non-commercial use only.
11
;  All other rights reserved.
12
;
13
; ==========================================================================
14
 
15
 
16
;; --------------------------------------------------------------------------
17
;;  Lead Engine handler called by SIDSE_Handler (sid_se.inc)
18
;; --------------------------------------------------------------------------
19
SIDSE_L_Handler
20
	SET_BSR	SID_BASE		; prepare BSR for SID register access
21
 
22
	;; branch depending on cycle
23
	BRA_IFSET SID_STAT, SID_STAT_SE_CYCLE, ACCESS, SIDSE_L_Handler_Cycle2
24
 
25
SIDSE_L_Handler_Cycle1
26
	bsf	SID_STAT, SID_STAT_SE_CYCLE	; on next handler call we want to process the second cycle
27
 
28
	;; clear "allocated" notification for external AOUTs - flags will be set if X2A function active
29
	clrf	SID_SE_EXT_ALLOCATED, BANKED
30
 
31
 
32
	;; ------------------------------------------------------------------
33
	;; 1st Cycle: LFOs
34
	;; ------------------------------------------------------------------
35
SIDSE_L_HANDLER_LFO_MACRO MACRO patch_base, lfo_base
36
	lfsr	FSR0, patch_base
37
	lfsr	FSR1, lfo_base
38
	call	SIDSE_L_LFO
39
	incf	SID_SE_ELEMENT_NUM, F, BANKED
40
	ENDM
41
 
42
	clrf	SID_SE_ELEMENT_NUM, BANKED
43
	SIDSE_L_HANDLER_LFO_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_LFO1_BASE, SID_LFO1_BASE
44
	SIDSE_L_HANDLER_LFO_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_LFO2_BASE, SID_LFO2_BASE
45
	SIDSE_L_HANDLER_LFO_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_LFO3_BASE, SID_LFO3_BASE
46
	SIDSE_L_HANDLER_LFO_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_LFO4_BASE, SID_LFO4_BASE
47
	SIDSE_L_HANDLER_LFO_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_LFO5_BASE, SID_LFO5_BASE
48
	SIDSE_L_HANDLER_LFO_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_LFO6_BASE, SID_LFO6_BASE
49
 
50
 
51
	;; ------------------------------------------------------------------
52
	;; 1st Cycle: Envelopes
53
	;; ------------------------------------------------------------------
54
SIDSE_L_HANDLER_ENV_MACRO MACRO patch_base, env_base
55
	lfsr	FSR0, patch_base
56
	lfsr	FSR1, env_base
57
	call	SIDSE_L_ENV
58
	incf	SID_SE_ELEMENT_NUM, F, BANKED
59
	ENDM
60
 
61
	clrf	SID_SE_ELEMENT_NUM, BANKED
62
	SIDSE_L_HANDLER_ENV_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_ENV1_BASE, SID_ENV1_BASE
63
	SIDSE_L_HANDLER_ENV_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_ENV2_BASE, SID_ENV2_BASE
64
 
65
 
66
	;; ------------------------------------------------------------------
67
	;; 1st Cycle: Modulation Matrix
68
	;; ------------------------------------------------------------------
69
 
70
	;; clear modulation targets
71
	movlw	((SID_MOD_TARG_CLEAR_END-SID_MOD_TARG_CLEAR_BEGIN)+1) & 0xff
72
	movwf	IRQ_TMP1
73
	lfsr	FSR0, SID_MOD_TARG_CLEAR_BEGIN
74
SIDSE_L_Handler_ModClearLoop
75
	clrf	POSTINC0
76
	decfsz	IRQ_TMP1, F
77
	rgoto	SIDSE_L_Handler_ModClearLoop
78
 
398 tk 79
	;; since this isn't done anywhere else:
80
#if 0
81
	;; convert key number of voice1 to 15bit signed value, centered at 60 (middle-C)
82
	movff	SIDL_V1_BASE + SID_Vx_TRANSP_NOTE, WREG
83
	addlw	-60
84
	movwf	SID_MOD_SRC_L_KEY_H, BANKED
85
	movlw	0x00
86
	btfsc	SID_MOD_SRC_L_KEY_H, 7, BANKED
87
	movlw 0xff
88
	movwf	SID_MOD_SRC_L_KEY_L, BANKED
89
#else
90
	;; modulation only in positive direction
91
	clrf	SID_MOD_SRC_L_KEY_L, BANKED
875 tk 92
#if 0
93
	movff	SIDL_V1_BASE + SID_Vx_TRANSP_NOTE,
94
#else
95
	;; use linear frequency instead, so that sweeps are considered as well
96
	movff   SIDL_V1_BASE + SID_Vx_LINEAR_FRQ_H, SID_MOD_SRC_L_KEY_H
97
	clrc
98
	rrf	SID_MOD_SRC_L_KEY_H, F, BANKED
398 tk 99
#endif
875 tk 100
#endif
1 tk 101
 
398 tk 102
	;; copy knob1 to MDW source
103
	;; in distance to Knob1, this one goes only into positive direction
104
	clrf	SID_MOD_SRC_L_MDW_L, BANKED
105
	movf	SID_MOD_SRC_L_KNOB1_H, W, BANKED
106
	addlw	0x80
107
	rrf	WREG, W
108
	andlw	0x7f
109
	movwf	SID_MOD_SRC_L_MDW_H, BANKED
110
 
111
 
1 tk 112
SIDSE_L_HANDLER_MOD_MACRO MACRO patch_base
113
	lfsr	FSR0, patch_base
114
	call	SIDSE_L_MOD
115
	incf	SID_SE_ELEMENT_NUM, F, BANKED
116
	ENDM
117
 
118
	clrf	SID_SE_ELEMENT_NUM, BANKED
119
	SIDSE_L_HANDLER_MOD_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_MOD1_BASE
120
	SIDSE_L_HANDLER_MOD_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_MOD2_BASE
121
	SIDSE_L_HANDLER_MOD_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_MOD3_BASE
122
	SIDSE_L_HANDLER_MOD_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_MOD4_BASE
123
	SIDSE_L_HANDLER_MOD_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_MOD5_BASE
124
	SIDSE_L_HANDLER_MOD_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_MOD6_BASE
125
	SIDSE_L_HANDLER_MOD_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_MOD7_BASE
126
	SIDSE_L_HANDLER_MOD_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_MOD8_BASE
127
 
128
	rgoto	SIDSE_L_Handler_End
129
 
130
 
131
SIDSE_L_Handler_Cycle2
132
	bcf	SID_STAT, SID_STAT_SE_CYCLE	; on next handler call we want to process the first cycle
133
 
134
 
135
	;; ------------------------------------------------------------------
136
	;; 2nd Cycle: Clock Handler
137
	;; ------------------------------------------------------------------
138
	call	SIDSE_Clk
139
 
140
 
141
	;; ------------------------------------------------------------------
142
	;; 2nd Cycle: Wavetable Handler
143
	;; ------------------------------------------------------------------
144
SIDSE_L_HANDLER_WT_MACRO MACRO patch_base, wt_base
145
	lfsr	FSR0, patch_base
146
	lfsr	FSR2, wt_base
147
   	rcall	SIDSE_L_WT
148
	incf	SID_SE_ELEMENT_NUM, F, BANKED
149
	ENDM
150
 
151
	clrf	SID_SE_ELEMENT_NUM, BANKED
152
	SIDSE_L_HANDLER_WT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_WT1_BASE, SID_WT1_BASE
153
	SIDSE_L_HANDLER_WT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_WT2_BASE, SID_WT2_BASE
154
	SIDSE_L_HANDLER_WT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_WT3_BASE, SID_WT3_BASE
155
	SIDSE_L_HANDLER_WT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_WT4_BASE, SID_WT4_BASE
156
 
157
	;; clear all WT requests
158
	clrf	SID_SE_TRG_EVNT_U, BANKED
159
 
160
 
161
	;; ------------------------------------------------------------------
162
	;; 2nd Cycle: Arp Handler
163
	;; ------------------------------------------------------------------
164
SIDSE_L_HANDLER_ARP_MACRO MACRO patch_base, voice_base, midi_voice_base
165
	lfsr	FSR0, patch_base
166
	lfsr	FSR1, voice_base
167
	lfsr	FSR2, midi_voice_base
168
	call	SIDSE_Arp
169
	incf	SID_SE_ELEMENT_NUM, F, BANKED
170
	ENDM
171
 
172
	clrf	SID_SE_ELEMENT_NUM, BANKED
173
SIDSE_L_Handler_Arp_L
174
	SIDSE_L_HANDLER_ARP_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1V1_BASE, SIDL_V1_BASE, SID_MV1_BASE
175
	SIDSE_L_HANDLER_ARP_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1V2_BASE, SIDL_V2_BASE, SID_MV2_BASE
176
	SIDSE_L_HANDLER_ARP_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1V3_BASE, SIDL_V3_BASE, SID_MV3_BASE
177
 
178
	movff	SID_LOCAL_ENS + SID_ENSx_CTRL1, WREG
179
	BRA_IFSET WREG, SID_ENS_CTRL1_MONO, ACCESS, SIDSE_L_Handler_Arp_NotR
180
SIDSE_L_Handler_Arp_R
181
	SIDSE_L_HANDLER_ARP_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2V1_BASE, SIDR_V1_BASE, SID_MV4_BASE
182
	SIDSE_L_HANDLER_ARP_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2V2_BASE, SIDR_V2_BASE, SID_MV5_BASE
183
	SIDSE_L_HANDLER_ARP_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2V3_BASE, SIDR_V3_BASE, SID_MV6_BASE
184
SIDSE_L_Handler_Arp_NotR
185
 
186
 
187
	;; ------------------------------------------------------------------
188
	;; 2nd Cycle: check ENV/LFO/Note Sync requests
189
	;; ------------------------------------------------------------------
190
	call	SIDSE_L_Sync
191
 
192
 
193
	;; ------------------------------------------------------------------
194
	;; 2nd Cycle: Voices
195
	;; ------------------------------------------------------------------
196
SIDSE_L_HANDLER_NOTE_MACRO MACRO patch_base, voice_base
197
	lfsr	FSR0, patch_base
198
	lfsr	FSR1, voice_base
199
	rcall	SIDSE_L_Note
200
	incf	SID_SE_ELEMENT_NUM, F, BANKED
201
	ENDM
202
 
203
	clrf	SID_SE_ELEMENT_NUM, BANKED
204
SIDSE_L_Handler_Note_L
205
	SIDSE_L_HANDLER_NOTE_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1V1_BASE, SIDL_V1_BASE
206
	SIDSE_L_HANDLER_NOTE_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1V2_BASE, SIDL_V2_BASE
207
	SIDSE_L_HANDLER_NOTE_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1V3_BASE, SIDL_V3_BASE
208
 
209
	movff	SID_LOCAL_ENS + SID_ENSx_CTRL1, WREG
210
	BRA_IFSET WREG, SID_ENS_CTRL1_MONO, ACCESS, SIDSE_L_Handler_Note_NotR
211
SIDSE_L_Handler_Note_R
212
	SIDSE_L_HANDLER_NOTE_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2V1_BASE, SIDR_V1_BASE
213
	SIDSE_L_HANDLER_NOTE_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2V2_BASE, SIDR_V2_BASE
214
	SIDSE_L_HANDLER_NOTE_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2V3_BASE, SIDR_V3_BASE
215
SIDSE_L_Handler_Note_NotR
216
 
217
	;; ------------------------------------------------------------------
218
	;; 2nd Cycle: Filter
219
	;; ------------------------------------------------------------------
220
 
221
SIDSE_L_Handler_Filter_L
222
	clrf	SID_SE_ELEMENT_NUM, BANKED
223
	lfsr	FSR0, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1F_BASE
224
	lfsr	FSR1, SID_MOD_TARG_FIL1_L
225
	lfsr	FSR2, SIDL_BASE
226
	call	SIDSE_Filter
227
 
228
	movff	SID_LOCAL_ENS + SID_ENSx_CTRL1, WREG
229
	BRA_IFSET WREG, SID_ENS_CTRL1_MONO, ACCESS, SIDSE_L_Handler_Filter_NotR
230
SIDSE_L_Handler_Filter_R
231
	incf	SID_SE_ELEMENT_NUM, F, BANKED
232
	lfsr	FSR0, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2F_BASE
233
	lfsr	FSR1, SID_MOD_TARG_FIL2_L
234
	lfsr	FSR2, SIDR_BASE
235
	call	SIDSE_Filter
236
SIDSE_L_Handler_Filter_NotR
237
 
238
	;; ------------------------------------------------------------------
239
	;; 2nd Cycle: AOUTs (External/Extensions)
240
	;; ------------------------------------------------------------------
136 tk 241
SIDSE_L_HANDLER_EXT_MACRO MACRO patch_base, mod_base
1 tk 242
	lfsr	FSR0, patch_base
243
	lfsr	FSR2, mod_base
244
	call	SIDSE_L_EXT
245
	incf	SID_SE_ELEMENT_NUM, F, BANKED
246
	ENDM
247
 
248
	clrf	SID_SE_ELEMENT_NUM, BANKED
136 tk 249
	SIDSE_L_HANDLER_EXT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_EXT_PAR1_L, SID_MOD_TARG_EXT1_L
250
	SIDSE_L_HANDLER_EXT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_EXT_PAR2_L, SID_MOD_TARG_EXT2_L
251
	SIDSE_L_HANDLER_EXT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_EXT_PAR3_L, SID_MOD_TARG_EXT3_L
252
	SIDSE_L_HANDLER_EXT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_EXT_PAR4_L, SID_MOD_TARG_EXT4_L
253
	SIDSE_L_HANDLER_EXT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_EXT_PAR5_L, SID_MOD_TARG_EXT5_L
254
	SIDSE_L_HANDLER_EXT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_EXT_PAR6_L, SID_MOD_TARG_EXT6_L
255
	SIDSE_L_HANDLER_EXT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_EXT_PAR7_L, SID_MOD_TARG_EXT7_L
256
	SIDSE_L_HANDLER_EXT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_EXT_PAR8_L, SID_MOD_TARG_EXT8_L
1 tk 257
 
258
 
259
	;; ------------------------------------------------------------------
260
	;; 2nd Cycle: External Switches
261
	;; ------------------------------------------------------------------
262
	call	SIDSE_EXT_Switches
263
 
264
 
265
	;; ------------------------------------------------------------------
266
	;; call temporary routine which updates static SID registers
267
	;; ------------------------------------------------------------------
268
 
269
	rcall	SIDSE_L_UpdateStatRegs
270
 
271
 
272
	;; ------------------------------------------------------------------
828 tk 273
	;; 2nd Cycle: LED Matrix Update
274
	;; ------------------------------------------------------------------
275
	call	SIDSE_L_CS_LM
276
 
277
 
278
	;; ------------------------------------------------------------------
1 tk 279
	;; clear FA/FB and FC synch request
280
	;; ------------------------------------------------------------------
281
	bcf	SID_SE_STATE, SID_SE_STATE_MIDI_CLK_FA_REQ, BANKED
282
	bcf	SID_SE_STATE, SID_SE_STATE_MIDI_CLK_FB_REQ, BANKED
283
	bcf	SID_SE_STATE, SID_SE_STATE_MIDI_CLK_FC_REQ, BANKED
284
 
285
SIDSE_L_Handler_End
286
	return
287
 
288
 
289
;; --------------------------------------------------------------------------
290
;;  Updates static SID registers
291
;;  (temporary)
292
;; --------------------------------------------------------------------------
293
SIDSE_L_UpdateStatRegs
294
SIDSE_UPDATESTAT_MACRO	MACRO p_base, sid_base, swinsid_mode, swinsid_phase
295
	LOCAL	SIDSE_L_UpdateStatRegs_NoADSR
296
 
297
	lfsr	FSR0, p_base
298
 
299
	movlw	0x09
300
	andwf	sid_base + SIDx_V1_CTRL, F, BANKED
301
	movlw	SID_Ix_Vx_WAVEFORM
302
	swapf	PLUSW0, W
303
	andlw	0xf6
805 tk 304
#if DEFAULT_ENABLE_UPPER_WAVEFORMS == 0
305
	;; disable to allow nice effects in conjunction with testbit
1 tk 306
	btfsc	WREG, 7; ensure that noise will not "lock on" like described in 6581 spec
805 tk 307
	andlw	0x8f
308
#else
309
#if 0
310
	;; optional WT hack - see http://www.midibox.org/forum/index.php/topic,13898.0.html
311
	;; and http://www.dekadence64.org/sidwav.txt
312
	;; In order to test this, use following WT sequence assigned to Waveform of OSC1 (or OSC1/2/3)
313
	;; 00: 0F
314
	;; 01: 00
315
	;; 02: 08
316
	;; Begin: 00, End: 08, Loop: 00, Speed: 1..4
317
	skpz
318
	bcf	sid_base + SIDx_V1_CTRL, 3 ; ensure that testflag not set
319
	skpnz
320
	iorlw	0x08		; set testflag if all waveforms disabled
321
#endif
322
#endif
1 tk 323
	iorwf	sid_base + SIDx_V1_CTRL, F, BANKED
324
 
878 tk 325
	;; if ABW (ADSR bug workaround) function active, ADSR registers will be controlled by SIDSE_Gate
1 tk 326
	movff	SID_PATCH_BUFFER_SHADOW + SID_Ix_OPT1_FLAGS, WREG
327
	BRA_IFSET WREG, SID_I_OPT1_FLAGS_ABW, ACCESS, SIDSE_L_UpdateStatRegs_NoADSR
328
	movlw	SID_Ix_Vx_AD
329
	movff	PLUSW0, sid_base + SIDx_V1_ENV_AD
330
	movlw	SID_Ix_Vx_SR
331
	movff	PLUSW0, sid_base + SIDx_V1_ENV_SR
332
SIDSE_L_UpdateStatRegs_NoADSR
805 tk 333
#if DEFAULT_ENABLE_SWINSID
1 tk 334
	movlw	SID_Ix_Vx_SWINSID_MODE
335
	movff	PLUSW0, swinsid_mode
336
	movlw	SID_Ix_Vx_SWINSID_PHASE
337
	movff	PLUSW0, swinsid_phase
338
#endif
339
	ENDM
340
 
341
	SET_BSR	SIDL_BASE
342
 
343
	SIDSE_UPDATESTAT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1V1_BASE, SIDL_BASE + SIDx_V1_FRQ_L, SIDL_BASE + SIDx_SWINSID_V1_MODE, SIDL_BASE + SIDx_SWINSID_V1_PHASE
344
	SIDSE_UPDATESTAT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1V2_BASE, SIDL_BASE + SIDx_V2_FRQ_L, SIDL_BASE + SIDx_SWINSID_V2_MODE, SIDL_BASE + SIDx_SWINSID_V2_PHASE
345
	SIDSE_UPDATESTAT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1V3_BASE, SIDL_BASE + SIDx_V3_FRQ_L, SIDL_BASE + SIDx_SWINSID_V3_MODE, SIDL_BASE + SIDx_SWINSID_V3_PHASE
346
 
347
	;; in Mono mode: copy *ALL* SID registers (not only the static ones) over to SIDR
348
	movff	SID_LOCAL_ENS + SID_ENSx_CTRL1, WREG
349
	BRA_IFSET WREG, SID_ENS_CTRL1_MONO, ACCESS, SIDSE_L_UpdateStatRegs_Mono
350
SIDSE_L_UpdateStatRegs_Stereo
351
	;; stereo mode:	most SIDs registers already updated, copy over the static ones
352
	SIDSE_UPDATESTAT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2V1_BASE, SIDR_BASE + SIDx_V1_FRQ_L, SIDR_BASE + SIDx_SWINSID_V1_MODE, SIDR_BASE + SIDx_SWINSID_V1_PHASE
353
	SIDSE_UPDATESTAT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2V2_BASE, SIDR_BASE + SIDx_V2_FRQ_L, SIDR_BASE + SIDx_SWINSID_V2_MODE, SIDR_BASE + SIDx_SWINSID_V2_PHASE
354
	SIDSE_UPDATESTAT_MACRO SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2V3_BASE, SIDR_BASE + SIDx_V3_FRQ_L, SIDR_BASE + SIDx_SWINSID_V3_MODE, SIDR_BASE + SIDx_SWINSID_V3_PHASE
355
	rgoto	SIDSE_L_UpdateStatRegs_End
356
 
357
 
358
SIDSE_L_UpdateStatRegs_Mono
359
	;; mono mode: copy over *all* SID registers of SIDL to SIDR
360
	lfsr	FSR1, SIDL_BASE
361
	lfsr	FSR2, SIDR_BASE
805 tk 362
#if DEFAULT_ENABLE_SWINSID
1 tk 363
	movlw	0x20
364
#else
365
	movlw	SIDx_MODE_VOL+1
366
#endif
367
	movwf	PRODL		; (loop counter)
368
SIDSE_L_UpdateStatRegs_Mono_Loop
369
	movff	POSTINC1, POSTINC2
370
	decfsz	PRODL, F
371
	rgoto	SIDSE_L_UpdateStatRegs_Mono_Loop
372
 
373
SIDSE_L_UpdateStatRegs_End
374
	SET_BSR	SID_BASE
375
	return
376
 
377
 
378
;; --------------------------------------------------------------------------
379
;; This function handles the notes (gate/pitch/PW)
380
;; IN: pointer to SID_Ix_e_SxVy_BASE in FSR0 (patch record)
381
;;     pointer to SIDx_Vx_BASE in FSR1 (voice record)
382
;;     Voice number in SID_SE_ELEMENT_NUM
383
;; --------------------------------------------------------------------------
384
SIDSE_L_Note
385
	call	SIDSE_Gate	; gate handler
386
	skpz			; returns ZERO flag cleared if pitch should not be changed
387
   	call	SIDSE_Pitch	; pitch handler
388
	goto	SIDSE_PW	; pulsewidth handler
389
 
390
 
391
;; --------------------------------------------------------------------------
392
;; This function handles the wavetables
393
;; IN: pointer to SID_Ix_WTx_BASE in FSR0 (patch record)
394
;;     pointer to SID_WTx_BASE in FSR2 (wt record)
395
;;     WT number in SID_SE_ELEMENT_NUM
396
;; --------------------------------------------------------------------------
397
SIDSE_L_WT
867 tk 398
	;; if KEY control flag (END[7]) set, control position from current played key
399
	movlw	SID_Ix_WTx_END
400
	BRA_IFCLR PLUSW0, 7, ACCESS, SIDSE_L_WT_NoKey
401
SIDSE_L_WT_Key
402
	;; copy currently played note (of first voice) * 2 to IRQ_TMP2
403
	movff	SIDL_V1_BASE + SID_Vx_PLAYED_NOTE, IRQ_TMP2
404
	clrc
405
	rlf	IRQ_TMP2, F
406
 
407
	;; continue at modulation handler (same code - to save code space)
408
	rgoto	SIDSE_L_WT_Key_Cont
409
SIDSE_L_WT_NoKey
410
 
411
	;;
878 tk 412
	;; if MOD control flag (BEGIN[7]) set, control position from modulation matrix
1 tk 413
	movlw	SID_Ix_WTx_BEGIN
414
	BRA_IFCLR PLUSW0, 7, ACCESS, SIDSE_L_WT_NoMOD
415
SIDSE_L_WT_MOD
416
	;; determine pointer to modulation target value -> FSR1
417
	movf	SID_SE_ELEMENT_NUM, W, BANKED
418
	addlw	(SID_MOD_TARG_WT1_L-SID_MOD_TARG_BASE)/3
419
	mullw	3
420
	lfsr	FSR1, SID_MOD_TARG_BASE
421
	movf	PRODL, W
422
	addwf	FSR1L, F
423
 
424
	;; convert modulation target value to 8bit absolute value
425
	movff	POSTINC1, IRQ_TMP1
426
	movff	POSTINC1, IRQ_TMP2
427
	movff	POSTINC1, IRQ_TMP3
428
 
429
	movlw	0x80
430
	addwf	IRQ_TMP2, F
431
 
432
	;; saturate
433
	BRA_IFSET IRQ_TMP3, 7, ACCESS, SIDSE_L_WT_MOD_SatNeg
434
SIDSE_L_WT_MOD_SatPos
435
	movf	IRQ_TMP3, W
436
	bnz	SIDSE_L_WT_MOD_SatPos_Sat
437
	bnc	SIDSE_L_WT_MOD_NoSat
438
SIDSE_L_WT_MOD_SatPos_Sat
439
	setf	IRQ_TMP2
440
	rgoto	SIDSE_L_WT_MOD_Sat_Cont
441
SIDSE_L_WT_MOD_SatNeg
442
	comf	IRQ_TMP3, W
443
	bnz	SIDSE_L_WT_MOD_SatNeg_Sat
444
	bc	SIDSE_L_WT_MOD_NoSat
445
SIDSE_L_WT_MOD_SatNeg_Sat
446
	clrf	IRQ_TMP2
447
	;; 	rgoto	SIDSE_L_WT_MOD_Sat_Cont
448
SIDSE_L_WT_MOD_NoSat
449
SIDSE_L_WT_MOD_Sat_Cont
450
 
867 tk 451
 
452
	;; following part also used by KEY flag
453
SIDSE_L_WT_Key_Cont
454
	;; determine range: END-BEGIN+1 -> IRQ_TMP5
455
	;; start value -> IRQ_TMP4 (either END or BEGIN, depending on polarity)
456
	movlw	SID_Ix_WTx_END
457
	movf	PLUSW0, W
458
	andlw	0x7f
459
	movwf	IRQ_TMP5
460
	movlw	SID_Ix_WTx_BEGIN
461
	movf	PLUSW0, W
462
	andlw	0x7f
463
	movwf	IRQ_TMP4
464
	subwf	IRQ_TMP5, F
465
	;; n+1 complement if begin greater than end
466
	BRA_IFCLR IRQ_TMP5, 7, ACCESS, SIDSE_L_WT_MOD_NoRngInv
467
SIDSE_L_WT_MOD_RngInv
468
	comf	IRQ_TMP5, F
469
	incf	IRQ_TMP5, F
470
	movlw	SID_Ix_WTx_END
471
	movf	PLUSW0, W
472
	andlw	0x7f
473
	movwf	IRQ_TMP4
474
SIDSE_L_WT_MOD_NoRngInv
475
	incf	IRQ_TMP5, F
476
 
1 tk 477
	;; determine position
478
	movf	IRQ_TMP5, W		; range
479
	mulwf	IRQ_TMP2, ACCESS	; modulation value
480
	movf	PRODH, W		; scaled value
481
 	addwf	IRQ_TMP4, F		; add to begin position
482
 
867 tk 483
#if 0
1 tk 484
	;; play new step if position has been changed
485
	movlw	SID_WTx_POS
486
	movf	PLUSW2, W
487
	xorwf	IRQ_TMP4, W
488
	bz	SIDSE_L_WT_End
867 tk 489
#endif
490
	;; changed: always play new position
491
	;; important while wavetable is edited
492
 
1 tk 493
	movlw	SID_WTx_POS
494
	movff	IRQ_TMP4, PLUSW2
495
	rgoto	SIDSE_L_WT_PlayStep
496
 
497
 
498
 
499
	;; normal WT mode
500
SIDSE_L_WT_NoMOD
501
	;; clear temporary WT flags
502
	bcf	SID_SE_STATE, SID_SE_STATE_WT_NEW_STEP_REQ, BANKED
503
 
504
	;; check if WT reset requested
505
	movf	SID_SE_ELEMENT_NUM, W, BANKED
506
	addlw	SID_TRG_TARGET_U_W1R
507
	call	MIOS_HLP_GetBitORMask
508
	andwf	SID_SE_TRG_EVNT_U, W, BANKED
509
	bz	SIDSE_L_WT_NoDivReset
510
SIDSE_L_WT_DivReset
511
	;; next clock event will increment div to 0
512
	movlw	SID_WTx_DIV_CTR
513
	setf	PLUSW2
514
	;; next step will increment to start position
515
	movlw	SID_Ix_WTx_BEGIN
516
	movf	PLUSW0, W
517
	andlw	0x7f
518
	addlw	-1
519
	movwf	PRODL
520
	movlw	SID_WTx_POS
521
	movff	PRODL, PLUSW2
522
SIDSE_L_WT_NoDivReset
523
 
524
	;; check for clock sync event
525
	movf	SID_SE_ELEMENT_NUM, W, BANKED
526
	addlw	SID_TRG_TARGET_U_W1S
527
	call	MIOS_HLP_GetBitORMask
528
	andwf	SID_SE_TRG_EVNT_U, W, BANKED
529
	bz	SIDSE_L_WT_NoClk
530
SIDSE_L_WT_Clk
531
	;; increment clock divider
532
	;; reset divider if it already has reached the target value
533
	movlw	SID_WTx_DIV_CTR
534
	incf	PLUSW2, W
535
	movwf	PRODL
536
	bz	SIDSE_L_WT_Clk_Ov
537
 
538
	;; reset once max value is reached
539
	movlw	SID_Ix_WTx_SPEED
540
	movf	PLUSW0, W
541
	andlw	0x3f
542
	cpfsgt	PRODL, ACCESS
543
	rgoto SIDSE_L_WT_Clk_NoOv
544
SIDSE_L_WT_Clk_Ov
545
	clrf	PRODL
546
	;; request next step
547
	bsf	SID_SE_STATE, SID_SE_STATE_WT_NEW_STEP_REQ, BANKED
548
SIDSE_L_WT_Clk_NoOv
549
	;; transfer new divider value into WTx register
550
	movlw	SID_WTx_DIV_CTR
551
	movff	PRODL, PLUSW2
552
SIDSE_L_WT_NoClk
553
 
554
	;; skip if no new step requested
555
	BRA_IFCLR SID_SE_STATE, SID_SE_STATE_WT_NEW_STEP_REQ, BANKED, SIDSE_L_WT_End
556
 
557
	;; skip if position is 0xaa (notifies oneshot -> WT stopped)
558
	movlw	SID_WTx_POS
559
	movf	PLUSW2, W
560
	xorlw	0xaa
561
	bz	SIDSE_L_WT_End
562
 
563
SIDSE_L_WT_NextStep
564
	;; increment position counter, reset at end position
565
	movlw	SID_WTx_POS
566
	incf	PLUSW2, W
567
	movwf	PRODL
568
	movlw	SID_Ix_WTx_END
569
	movf	PLUSW0, W
570
	andlw	0x7f
571
	cpfsgt	PRODL, ACCESS
572
	rgoto SIDSE_L_WT_NextStep_NoOv
573
SIDSE_L_WT_NextStep_Ov
574
	;; if one-shot mode: set position to 0xaa, WT is stopped now!
575
	movlw	SID_Ix_WTx_LOOP
576
	BRA_IFCLR PLUSW0, 7, ACCESS, SIDSE_L_WT_NextStep_Ov_NoOneShot
577
SIDSE_L_WT_NextStep_Ov_OneShot
578
	movlw	0xaa
579
	movwf	PRODL
580
	movlw	SID_WTx_POS
581
	movff	PRODL, PLUSW2
582
	rgoto	SIDSE_L_WT_End
583
 
584
SIDSE_L_WT_NextStep_Ov_NoOneShot
585
	movlw	SID_Ix_WTx_LOOP
586
	movf	PLUSW0, W
587
	andlw	0x7f
588
	movwf	PRODL
589
SIDSE_L_WT_NextStep_NoOv
590
	;; transfer back to position counter
591
	movlw	SID_WTx_POS
592
	movff	PRODL, PLUSW2
593
 
594
	;; "play" the step
867 tk 595
	;; (entry point for SIDSE_L_WT_MOD_ and KEY...)
1 tk 596
SIDSE_L_WT_PlayStep
597
	;; get pointer to WT value
598
	lfsr	FSR1, SID_PATCH_BUFFER_SHADOW + SID_Ix_WAVETABLE
599
	movlw	SID_WTx_POS
600
	movf	PLUSW2, W
601
	andlw	0x7f
602
	addwf	FSR1L, F
603
 
604
	;; store value in MIOS_PARAMETER1
605
	movff	INDF1, MIOS_PARAMETER1
606
 
607
 
608
	;; forward to MOD matrix
609
	lfsr	FSR2, SID_MOD_SRC_L_WT1_L
610
	clrc
611
	rlf	SID_SE_ELEMENT_NUM, W, BANKED
612
	addwf	FSR2L, F
613
	;; branch depending on absolute (+0000..+7F00) and relative (-8000..+7FFF)
614
	BRA_IFSET MIOS_PARAMETER1, 7, ACCESS, SIDSE_L_WT_PlayStep_ModAbs
615
SIDSE_L_WT_PlayStep_ModRel
616
	;; convert to 15bit signed
617
	clrf	POSTINC2	; SID_MOD_SRC_L_WTx_VALUE_L
618
	clrc
619
	rlf	MIOS_PARAMETER1, W
620
	addlw	-0x80
621
	movwf	POSTDEC2	; SID_MOD_SRC_L_WTx_VALUE_H
622
	rgoto	SIDSE_L_WT_PlayStep_Mod_Cont
623
 
624
SIDSE_L_WT_PlayStep_ModAbs
625
	clrf	POSTINC2	; SID_MOD_SRC_L_WTx_VALUE_L
626
	movf	MIOS_PARAMETER1, W
627
	andlw	0x7f
628
	movwf	POSTDEC2	; SID_MOD_SRC_L_WTx_VALUE_H
629
	;; 	rgoto	SIDSE_L_WT_PlayStep_Mod_Cont
630
SIDSE_L_WT_PlayStep_Mod_Cont
631
 
632
 
633
	;; store SIDs which should be modified in MIOS_PARAMETER3[1:0]
634
	clrf	MIOS_PARAMETER3
635
	movlw	SID_Ix_WTx_SPEED
636
	btfsc	PLUSW0, 6
637
	bsf	MIOS_PARAMETER3, 0
638
	btfsc	PLUSW0, 7
639
	bsf	MIOS_PARAMETER3, 1
640
	;; call WT Parameter Handler
641
	movlw	SID_Ix_WTx_ASSGN
642
	movf	PLUSW0, W
643
	call	SID_PARIN_SetWT
644
 
645
SIDSE_L_WT_End
646
	return
647
 
648
 
649
 
650
;; --------------------------------------------------------------------------
651
;; This function syncs the LFOs/ENVs and Notes
652
;; IN: -
653
;; --------------------------------------------------------------------------
654
SIDSE_L_Sync
655
SIDSE_L_SYNC_ENV_MACRO	MACRO	evnt_a, evnt_a_flag, evnt_r, evnt_r_flag, patch_base, env_base
656
	lfsr	FSR0, patch_base
657
	lfsr	FSR1, env_base
658
	CALL_IFSET evnt_r, evnt_r_flag, BANKED, SIDSE_L_ENV_TrgRelease
659
	bcf	evnt_r, evnt_r_flag, BANKED
660
	CALL_IFSET evnt_a, evnt_a_flag, BANKED, SIDSE_L_ENV_Restart
661
	bcf	evnt_a, evnt_a_flag, BANKED
662
	ENDM
663
 
664
	SIDSE_L_SYNC_ENV_MACRO SID_SE_TRG_EVNT_L, SID_TRG_TARGET_L_E1A, SID_SE_TRG_EVNT_H, SID_TRG_TARGET_H_E1R, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_ENV1_BASE, SID_ENV1_BASE
665
	SIDSE_L_SYNC_ENV_MACRO SID_SE_TRG_EVNT_L, SID_TRG_TARGET_L_E2A, SID_SE_TRG_EVNT_H, SID_TRG_TARGET_H_E2R, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_ENV2_BASE, SID_ENV2_BASE
666
 
667
 
668
SIDSE_L_SYNC_LFO_MACRO	MACRO	evnt, evnt_flag, patch_base, lfo_base
669
	LOCAL	SIDSE_L_SYNC_LFO_Skip
670
 
671
	BRA_IFCLR evnt, evnt_flag, BANKED, SIDSE_L_SYNC_LFO_Skip
672
	lfsr	FSR0, patch_base
673
	lfsr	FSR1, lfo_base
674
	call	SIDSE_L_LFO_Restart
675
	bcf	evnt, evnt_flag, BANKED
676
SIDSE_L_SYNC_LFO_Skip
677
	incf	SID_SE_ELEMENT_NUM, F, BANKED
678
	ENDM
679
 
680
	clrf	SID_SE_ELEMENT_NUM, BANKED
681
	SIDSE_L_SYNC_LFO_MACRO SID_SE_TRG_EVNT_H, SID_TRG_TARGET_H_L1, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_LFO1_BASE, SID_LFO1_BASE
682
	SIDSE_L_SYNC_LFO_MACRO SID_SE_TRG_EVNT_H, SID_TRG_TARGET_H_L2, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_LFO2_BASE, SID_LFO2_BASE
683
	SIDSE_L_SYNC_LFO_MACRO SID_SE_TRG_EVNT_H, SID_TRG_TARGET_H_L3, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_LFO3_BASE, SID_LFO3_BASE
684
	SIDSE_L_SYNC_LFO_MACRO SID_SE_TRG_EVNT_H, SID_TRG_TARGET_H_L4, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_LFO4_BASE, SID_LFO4_BASE
685
	SIDSE_L_SYNC_LFO_MACRO SID_SE_TRG_EVNT_H, SID_TRG_TARGET_H_L5, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_LFO5_BASE, SID_LFO5_BASE
686
	SIDSE_L_SYNC_LFO_MACRO SID_SE_TRG_EVNT_H, SID_TRG_TARGET_H_L6, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_LFO6_BASE, SID_LFO6_BASE
687
 
688
 
689
SIDSE_L_SYNC_NOTE_MACRO	MACRO	evnt, evnt_flag, patch_base, voice_base
690
	LOCAL	SIDSE_L_SYNC_NOTE_Skip
691
 
692
	BRA_IFCLR evnt, evnt_flag, BANKED, SIDSE_L_SYNC_NOTE_Skip
693
	lfsr	FSR0, patch_base
694
	lfsr	FSR1, voice_base
695
	call	SIDSE_L_NOTE_Restart
696
	bcf	evnt, evnt_flag, BANKED
697
SIDSE_L_SYNC_NOTE_Skip
698
	incf	SID_SE_ELEMENT_NUM, F, BANKED
699
	ENDM
700
 
701
	clrf	SID_SE_ELEMENT_NUM, BANKED
702
	SIDSE_L_SYNC_NOTE_MACRO SID_SE_TRG_EVNT_L, SID_TRG_TARGET_L_O1L, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1V1_BASE, SIDL_V1_BASE
703
	SIDSE_L_SYNC_NOTE_MACRO SID_SE_TRG_EVNT_L, SID_TRG_TARGET_L_O2L, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1V2_BASE, SIDL_V2_BASE
704
	SIDSE_L_SYNC_NOTE_MACRO SID_SE_TRG_EVNT_L, SID_TRG_TARGET_L_O3L, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S1V3_BASE, SIDL_V3_BASE
705
	SIDSE_L_SYNC_NOTE_MACRO SID_SE_TRG_EVNT_L, SID_TRG_TARGET_L_O1R, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2V1_BASE, SIDR_V1_BASE
706
	SIDSE_L_SYNC_NOTE_MACRO SID_SE_TRG_EVNT_L, SID_TRG_TARGET_L_O2R, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2V2_BASE, SIDR_V2_BASE
707
	SIDSE_L_SYNC_NOTE_MACRO SID_SE_TRG_EVNT_L, SID_TRG_TARGET_L_O3R, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_S2V3_BASE, SIDR_V3_BASE
708
 
709
	return
710
 
711
 
712
;; --------------------------------------------------------------------------
713
;; This function handles the AOUTs
714
;; IN: pointer to SID_Ix_EXT_PARx_L in FSR0 (patch record)
715
;;     pointer to AOUTx_L in FSR1 (aout target)
716
;;     pointer to SID_MOD_TARG_EXTx_L in FSR2 (modulation value)
717
;;     EXT number in SID_SE_ELEMENT_NUM
718
;; --------------------------------------------------------------------------
719
SIDSE_L_EXT
720
	;; skip if any F2X function has already updated the AOUTx register
721
	movf	SID_SE_ELEMENT_NUM, W, BANKED
722
	call	MIOS_HLP_GetBitORMask
723
	andwf	SID_SE_EXT_ALLOCATED, W, BANKED
724
	bnz	SIDSE_L_EXT_End
725
 
136 tk 726
	;; store 16bit offset in MIOS_PARAMETER[12]
727
	movff	POSTINC0, MIOS_PARAMETER1
728
	movff	POSTDEC0, MIOS_PARAMETER2
1 tk 729
 
730
	;; pointer to SID_MOD_TARG_EXTx_L already in FSR2
731
	;; add modulation value to offset
732
	movf	POSTINC2, W
136 tk 733
	addwf	MIOS_PARAMETER1, F
1 tk 734
	movf	POSTINC2, W
136 tk 735
	addwfc	MIOS_PARAMETER2, F
1 tk 736
 
737
	;; saturate
738
	BRA_IFSET INDF2, 7, ACCESS, SIDSE_L_EXT_Mod_SatNeg
739
SIDSE_L_EXT_Mod_SatPos
740
	movf	INDF2, W
741
	bnz	SIDSE_L_EXT_Mod_SatPos_Sat
742
	bnc	SIDSE_L_EXT_Mod_Sat_NoSat
743
SIDSE_L_EXT_Mod_SatPos_Sat
136 tk 744
	setf	MIOS_PARAMETER1
745
	setf	MIOS_PARAMETER2
1 tk 746
	rgoto	SIDSE_L_EXT_Mod_Sat_Cont
747
SIDSE_L_EXT_Mod_SatNeg
748
	comf	INDF2, W
749
	bnz	SIDSE_L_EXT_Mod_SatNeg_Sat
750
	bc	SIDSE_L_EXT_Mod_Sat_NoSat
751
SIDSE_L_EXT_Mod_SatNeg_Sat
136 tk 752
	clrf	MIOS_PARAMETER1
753
	clrf	MIOS_PARAMETER2
1 tk 754
	;; 	rgoto	SIDSE_L_EXT_Mod_Sat_Cont
755
SIDSE_L_EXT_Mod_Sat_Cont
756
SIDSE_L_EXT_Mod_Sat_NoSat
757
 
136 tk 758
	movf	SID_SE_ELEMENT_NUM, W, BANKED
759
	call	AOUT_Pin16bitSet
760
	SET_BSR	SID_BASE
1 tk 761
 
762
SIDSE_L_EXT_End
763
	return
764
 
765
 
766
 
767
;; --------------------------------------------------------------------------
768
;; This function handles the LFOs (the SIDSE_L_LFO_Restart function restarts a LFO)
769
;; IN: pointer to SID_Ix_LFOx_BASE in FSR0 (patch record)
770
;;     pointer to SID_LFOx_BASE in FSR1
771
;;     LFO number in SID_SE_ELEMENT_NUM
772
;; --------------------------------------------------------------------------
773
SIDSE_L_LFO_Restart
774
	;; reset counter (take phase into account)
775
	movlw	0x00
776
	movwf	POSTINC1	; SID_LFOx_CTR_L
777
	movlw	SID_Ix_LFOx_PHASE
778
	movff	PLUSW0, POSTDEC1; SID_LFOx_CTR_H
779
 
780
	;; clear overrun flag (for oneshot mode)
781
	movf	SID_SE_ELEMENT_NUM, W, BANKED
782
	call	MIOS_HLP_GetBitANDMask
783
	andwf	SID_SE_LFO_OVERRUN, F, BANKED
784
 
785
	;; check if LFO should be delayed - set delay counter to 0x0001 in this case, else to 0x0000
786
	movlw	SID_LFOx_DELAY_CTR_H	; high byte always reset to 0
787
	clrf	PLUSW1
788
 
789
	movlw	SID_Ix_LFOx_DELAY
790
	clrf	PRODL			; low byte set to 1 if delay != 0
791
	movf	PLUSW0, W
792
	skpz
793
	incf	PRODL, F
794
	movlw	SID_LFOx_DELAY_CTR_L
795
	movff	PRODL, PLUSW1
796
 
797
	;; continue at waveform calculation
798
	rgoto	SIDSE_L_LFO_Restart_Cont
799
 
800
;; --------------------------------------------------------------------------
801
SIDSE_L_LFO			; normal LFO entry
802
	;; set wave register to initial value and skip LFO if not enabled
803
	movlw	SID_Ix_LFOx_MODE
804
	BRA_IFSET PLUSW0, SID_I_LFO_MODE_ENABLE, ACCESS, SIDSE_L_LFO_Enabled
805
SIDSE_L_LFO_Disabled
806
	lfsr	FSR2, SID_MOD_SRC_L_LFO1_L
807
	clrc
808
	rlf	SID_SE_ELEMENT_NUM, W, BANKED
809
	addwf	FSR2L, F
810
	clrf	POSTINC2	; SID_MOD_SRC_L_LFOx_VALUE_L
811
	clrf	POSTDEC2	; SID_MOD_SRC_L_LFOx_VALUE_H
812
	rgoto	SIDSE_L_LFO_End
813
SIDSE_L_LFO_Enabled
814
 
815
	;; temporary shift FSR1 to SID_LFOx_DELAY_CTR_L for easier handling
816
	movlw	SID_LFOx_DELAY_CTR_L
817
	addwf	FSR1L, F
818
 
819
	;; delay LFO so long 16bit delay counter != 0
820
	movf	POSTINC1, W
821
	iorwf	POSTDEC1, W
822
	bz	SIDSE_L_LFO_NoDelay
823
SIDSE_L_LFO_Delay
824
	;; increment counter, set it to zero on overrun (no delay anymore)
825
	movlw	SID_Ix_LFOx_DELAY
826
	movff	PLUSW0, IRQ_TMP3; incrementer is the same like used for envelopes
827
	movlw	0x80		; curve *must* be disabled!
828
	call	SIDSE_Hlp_ENV_GetBendedValue	; incrementer in MIOS_PARAMETER[12]
829
	movf	MIOS_PARAMETER1, W
830
	addwf	POSTINC1, F
831
	movf	MIOS_PARAMETER2, W
832
	addwfc	POSTDEC1, F
833
	bc	SIDSE_L_LFO_DelayOv
834
	rgoto	SIDSE_L_LFO_End
835
SIDSE_L_LFO_DelayOv
836
	;; overrun: clear counter to disable delay
837
	clrf	POSTINC1
838
	clrf	POSTDEC1
839
SIDSE_L_LFO_NoDelay
840
	movlw	-SID_LFOx_DELAY_CTR_L	; switch back to SID_LFOx_CTR_L
841
	addwf	FSR1L, F
842
 
843
	;; implementation: a LFO is just a 16bit ramp which is mapped to a waveform
844
 
845
	;; clear LFO overrun flag
846
	bcf	SID_SE_STATE, SID_SE_STATE_LFO_OVERRUN, BANKED
847
 
848
	;; in oneshot mode: check if overrun already occured
849
	movlw	SID_Ix_LFOx_MODE
850
	BRA_IFCLR PLUSW0, SID_I_LFO_MODE_ONESHOT, ACCESS, SIDSE_L_LFO_NoOneShotChk
851
SIDSE_L_LFO_OneShotChk
852
	movf	SID_SE_ELEMENT_NUM, W, BANKED
853
	call	MIOS_HLP_GetBitORMask
854
	andwf	SID_SE_LFO_OVERRUN, W, BANKED
855
	bz	SIDSE_L_LFO_NoOneShotChk
856
	;; set counter to maximum value and continue at waveform calculation
857
	setf	POSTINC1
858
	setf	POSTDEC1
859
	rgoto	SIDSE_L_LFO_OneShot_Cont
860
SIDSE_L_LFO_NoOneShotChk
861
 
875 tk 862
	;; if clock sync enabled: only increment on each 16th clock event
1 tk 863
	movlw	SID_Ix_LFOx_MODE
864
	BRA_IFCLR PLUSW0, SID_I_LFO_MODE_CLKSYNC, ACCESS, SIDSE_L_LFO_NoClkSync
865
SIDSE_L_LFO_ClkSync
866
	BRA_IFCLR SID_SE_STATE, SID_SE_STATE_GLOBAL_CLK_EVENT, BANKED, SIDSE_L_LFO_NoClk_Cont
248 tk 867
	movf	SID_SE_GLOBAL_CLK_CTR, W, BANKED
868
	andlw	0x0f
869
	bnz	SIDSE_L_LFO_NoClk_Cont
1 tk 870
SIDSE_L_LFO_NoClkSync
871
 
872
	;; increment 16bit counter by given rate
873
	movlw	SID_Ix_LFOx_RATE
874
	movff	PLUSW0, IRQ_TMP1
875
 
876
	;; rate can be modulated
877
 
878
	;; calculate pointer to MOD target array -> FSR2
879
	movf	SID_SE_ELEMENT_NUM, W, BANKED
880
	addlw	(SID_MOD_TARG_LR1_L-SID_MOD_TARG_BASE)/3
881
	mullw	3
882
	lfsr	FSR2, SID_MOD_TARG_BASE
883
	movf	PRODL, W
884
	addlw	1		; select SID_MOD_TARG_LRx_H
885
	addwf	FSR2L, F
886
	movf	POSTINC2, W
887
	addwf	IRQ_TMP1, F
888
 
889
	;; saturate
890
	BRA_IFSET INDF2, 7, ACCESS, SIDSE_L_LFO_Rate_SatNeg
891
SIDSE_L_LFO_RateNeg_SatPos
892
	movf	INDF2, W
893
	bnz	SIDSE_L_LFO_RateNeg_SatPos_Sat
894
	bnc	SIDSE_L_LFO_RateNeg_NoSat
895
SIDSE_L_LFO_RateNeg_SatPos_Sat
896
	setf	IRQ_TMP1
897
	rgoto	SIDSE_L_LFO_RateNeg_Sat_Cont
898
SIDSE_L_LFO_Rate_SatNeg
899
	comf	INDF2, W
900
	bnz	SIDSE_L_LFO_Rate_SatNeg_Sat
901
	bc	SIDSE_L_LFO_RateNeg_NoSat
902
SIDSE_L_LFO_Rate_SatNeg_Sat
903
	clrf	IRQ_TMP1
904
	;; 	rgoto	SIDSE_L_LFO_RateNeg_Sat_Cont
905
SIDSE_L_LFO_RateNeg_Sat_Cont
906
SIDSE_L_LFO_RateNeg_NoSat
907
 
908
	;; if LFO synched via clock, replace 245-255 by MIDI clock optimized incrementers
909
	movlw	SID_Ix_LFOx_MODE
910
	BRA_IFCLR PLUSW0, SID_I_LFO_MODE_CLKSYNC, ACCESS, SIDSE_L_LFO_Rate_NoClkSync
911
SIDSE_L_LFO_Rate_ClkSync
912
	movf	IRQ_TMP1, W
913
	addlw	-245
914
	bnc	SIDSE_L_LFO_Rate_NoClkSyncValues
915
	TABLE_ADDR_MUL_W SID_LFO_TABLE_MCLK, 2
916
	rgoto	SIDSE_L_LFO_Rate_ClkSync_Cont
917
SIDSE_L_LFO_Rate_NoClkSyncValues
918
SIDSE_L_LFO_Rate_NoClkSync
919
 
920
	movf	IRQ_TMP1, W
921
	TABLE_ADDR_MUL_W SID_LFO_TABLE, 2
922
SIDSE_L_LFO_Rate_ClkSync_Cont
923
	tblrd*+
924
	movf	TABLAT, W
925
	addwf	POSTINC1, F	; SID_LFOx_CTR_L
926
	tblrd*+
927
	movf	TABLAT, W
928
	addwfc	POSTDEC1, F	; SID_LFOx_CTR_H
929
	bnc	SIDSE_L_LFO_NoOverrun
930
 
931
SIDSE_L_LFO_Overrun
932
	;; required for S&H function below, will be cleared with each run
933
	bsf	SID_SE_STATE, SID_SE_STATE_LFO_OVERRUN, BANKED
934
 
935
	;; propagate overrun to trigger matrix (using FSR2 as working pointer)
936
	movf	SID_SE_ELEMENT_NUM, W, BANKED
937
	mullw	3
938
	lfsr	FSR2, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_TRG_L1P_BASE
939
	movf	PRODL, W
940
	addwf	FSR2L, F
941
	movf	POSTINC2, W
942
	iorwf	SID_SE_TRG_EVNT_L, F, BANKED
943
	movf	POSTINC2, W
944
	iorwf	SID_SE_TRG_EVNT_H, F, BANKED
945
	movf	POSTINC2, W
946
	iorwf	SID_SE_TRG_EVNT_U, F, BANKED
947
 
948
	;; required for one-shot mode, will be cleared with next gate trigger
949
	movf	SID_SE_ELEMENT_NUM, W, BANKED
950
	call	MIOS_HLP_GetBitORMask
951
	iorwf	SID_SE_LFO_OVERRUN, F, BANKED
952
 
953
	;; in oneshot mode: ensure that counter is set to maximum value
954
	movlw	SID_Ix_LFOx_MODE
955
	BRA_IFCLR PLUSW0, SID_I_LFO_MODE_ONESHOT, ACCESS, SIDSE_L_LFO_OverrunNoOneShot
956
SIDSE_L_LFO_OverrunOneShot
957
	setf	POSTINC1
958
	setf	POSTDEC1
959
SIDSE_L_LFO_OverrunNoOneShot
960
SIDSE_L_LFO_NoOverrun
961
 
962
SIDSE_L_LFO_OneShot_Cont		; entry point for oneshot function (if overrun already occured)
963
SIDSE_L_LFO_NoClk_Cont		; entry point for clock sync function (no clock event)
964
SIDSE_L_LFO_Restart_Cont		; entry point for restart function
965
 
966
#if 0
967
	;; DISABLED - for the case that depth is modulated we need to calculate the whole waveform
968
 
969
	;; skip the rest if depth is 0 (no waveform calculation required)
970
	movlw	SID_Ix_LFOx_DEPTH
971
	movf	PLUSW0, W
972
	xorlw	0x80
973
	skpnz
974
	rgoto	SIDSE_L_LFO_Zero
975
#endif
976
 
977
	;; temporary store SID_LFOx_CTR_[LH] in IRQ_TMP[12]
978
	movff	POSTINC1, IRQ_TMP1
979
	movff	POSTDEC1, IRQ_TMP2
980
 
981
	;; map to waveform
982
	;; result in MUL_A_[LH]
983
	movlw	SID_Ix_LFOx_MODE ; waveform selection in bit [6:4]
984
	swapf	PLUSW0, W
985
	BRA_IFSET WREG, 3, ACCESS, SIDSE_L_LFO_Wav89ABCDEF
986
SIDSE_L_LFO_Wav01234567
987
	BRA_IFSET WREG, 2, ACCESS, SIDSE_L_LFO_Wav4567
988
SIDSE_L_LFO_Wav0123
989
	BRA_IFSET WREG, 1, ACCESS, SIDSE_L_LFO_Wav23
990
SIDSE_L_LFO_Wav01
991
	BRA_IFSET WREG, 0, ACCESS, SIDSE_L_LFO_Wav1
992
 
993
	;; ------------------------------------------------------------------
994
SIDSE_L_LFO_Wav0	; Sine
995
	;; sine table contains a quarter of a sine,
996
	;; we have to negate/mirror it depending on the mapped counter value
997
	rlf	IRQ_TMP1, W
998
	rlf	IRQ_TMP2, W
999
	btfsc	IRQ_TMP2, 6
1000
	xorlw 0x7f
1001
	andlw	0x7f
1002
	TABLE_ADDR_MUL_W SID_SIN_TABLE, 2
1003
	tblrd*+
1004
	movff	TABLAT, MUL_A_L
1005
	tblrd*+
1006
	movff	TABLAT, MUL_A_H
1007
 
1008
	BRA_IFCLR IRQ_TMP2, 7, ACCESS, SIDSE_L_LFO_Wav0_NoNeg
1009
SIDSE_L_LFO_Wav0_Neg
1010
	comf	MUL_A_L, F, BANKED
1011
	comf	MUL_A_H, F, BANKED
1012
	incf	MUL_A_L, F, BANKED
1013
	skpnz
1014
	incf	MUL_A_H, F, BANKED
1015
SIDSE_L_LFO_Wav0_NoNeg
1016
 
1017
	rgoto	SIDSE_L_LFO_Wav_Cont
1018
 
1019
	;; ------------------------------------------------------------------
1020
SIDSE_L_LFO_Wav1	; Triangle
1021
	;; similar to sine, but linear waveform
1022
	clrc
1023
	rlf	IRQ_TMP1, W
1024
	movwf	MUL_A_L, BANKED
1025
	rlf	IRQ_TMP2, W
1026
	andlw	0x7f
1027
	movwf	MUL_A_H, BANKED
1028
 
1029
	BRA_IFCLR IRQ_TMP2, 6, ACCESS, SIDSE_L_LFO_Wav1_NoNeg1
1030
SIDSE_L_LFO_Wav1_Neg1
1031
	comf	MUL_A_L, BANKED
1032
	comf	MUL_A_H, BANKED
1033
	incf	MUL_A_L, F, BANKED
1034
	skpnz
1035
	incf	MUL_A_H, F, BANKED
1036
	bcf	MUL_A_H, 7, BANKED
1037
SIDSE_L_LFO_Wav1_NoNeg1
1038
 
1039
	BRA_IFCLR IRQ_TMP2, 7, ACCESS, SIDSE_L_LFO_Wav1_NoNeg2
1040
SIDSE_L_LFO_Wav1_Neg2
1041
	comf	MUL_A_L, F, BANKED
1042
	comf	MUL_A_H, F, BANKED
1043
	incf	MUL_A_L, F, BANKED
1044
	skpnz
1045
	incf	MUL_A_H, F, BANKED
1046
SIDSE_L_LFO_Wav1_NoNeg2
1047
 
1048
	rgoto	SIDSE_L_LFO_Wav_Cont
1049
 
1050
SIDSE_L_LFO_Wav23
1051
	BRA_IFSET WREG, 0, ACCESS, SIDSE_L_LFO_Wav3
1052
	;; ------------------------------------------------------------------
1053
SIDSE_L_LFO_Wav2	; Saw
1054
	;; this one is simple - it's "counter-0x8000"
1055
	movlw	0x00
1056
	subwf	IRQ_TMP1, W
1057
	movwf	MUL_A_L, BANKED
1058
	movlw	0x80
1059
	subwfb	IRQ_TMP2, W
1060
	movwf	MUL_A_H, BANKED
1061
 
1062
	rgoto	SIDSE_L_LFO_Wav_Cont
1063
 
1064
	;; ------------------------------------------------------------------
1065
SIDSE_L_LFO_Wav3	; Pulse
1066
	;; this one is even more simple
1067
	movlw	0x00
1068
	btfsc	IRQ_TMP2, 7
1069
	movlw 0xff
1070
	movwf	MUL_A_L, BANKED
1071
	movlw	0x80
1072
	btfsc	IRQ_TMP2, 7
1073
	movlw 0x7f
1074
	movwf	MUL_A_H, BANKED
1075
 
1076
	rgoto	SIDSE_L_LFO_Wav_Cont
1077
 
1078
SIDSE_L_LFO_Wav4567
1079
	BRA_IFSET WREG, 1, ACCESS, SIDSE_L_LFO_Wav67
1080
SIDSE_L_LFO_Wav45
1081
	BRA_IFSET WREG, 0, ACCESS, SIDSE_L_LFO_Wav5
1082
 
1083
	;; ------------------------------------------------------------------
1084
SIDSE_L_LFO_Wav4	; Random
1085
	;; only on LFO overrun:
1086
	BRA_IFCLR SID_SE_STATE, SID_SE_STATE_LFO_OVERRUN, BANKED, SIDSE_L_LFO_End
1087
 
1088
	;; generate new random number and copy it to MUL_A_[LH]
1089
	call	SID_RND_GenRandomNumber
1090
	movff	SID_RANDOM_SEED_L, MUL_A_L
1091
	movff	SID_RANDOM_SEED_L, MUL_A_H
1092
 
1093
	rgoto	SIDSE_L_LFO_Wav_Cont
1094
 
1095
	;; ------------------------------------------------------------------
1096
SIDSE_L_LFO_Wav5	; positive sine
1097
	;; sine table contains a quarter of a sine,
1098
	;; we have to negate/mirror it depending on the mapped counter value
1099
	movf	IRQ_TMP2, W
1100
	btfsc	IRQ_TMP2, 7
1101
	xorlw 0x7f
1102
	andlw	0x7f
1103
	TABLE_ADDR_MUL_W SID_SIN_TABLE, 2
1104
	tblrd*+
1105
	movff	TABLAT, MUL_A_L
1106
	tblrd*+
1107
	movff	TABLAT, MUL_A_H
1108
 
1109
	rgoto	SIDSE_L_LFO_Wav_Cont
1110
 
1111
 
1112
SIDSE_L_LFO_Wav67
1113
	BRA_IFSET WREG, 0, ACCESS, SIDSE_L_LFO_Wav7
1114
 
1115
	;; ------------------------------------------------------------------
1116
SIDSE_L_LFO_Wav6	; positive triangle
1117
	movff	IRQ_TMP1, MUL_A_L
1118
	movff	IRQ_TMP2, MUL_A_H
1119
 
1120
	BRA_IFCLR IRQ_TMP2, 7, ACCESS, SIDSE_L_LFO_Wav6_NoNeg
1121
SIDSE_L_LFO_Wav6_Neg
1122
	comf	MUL_A_L, BANKED
1123
	comf	MUL_A_H, BANKED
1124
	incf	MUL_A_L, F, BANKED
1125
	skpnz
1126
	incf	MUL_A_H, F, BANKED
1127
	bcf	MUL_A_H, 7, BANKED
1128
SIDSE_L_LFO_Wav6_NoNeg
1129
 
1130
	rgoto	SIDSE_L_LFO_Wav_Cont
1131
 
1132
	;; ------------------------------------------------------------------
1133
SIDSE_L_LFO_Wav7	; positive saw
1134
	clrc
1135
	rrf	IRQ_TMP2, W
1136
	movwf	MUL_A_H, BANKED
1137
	rrf	IRQ_TMP1, W
1138
	movwf	MUL_A_L, BANKED
1139
 
1140
	rgoto	SIDSE_L_LFO_Wav_Cont
1141
 
1142
	;; ------------------------------------------------------------------
1143
SIDSE_L_LFO_Wav89ABCDEF	; positive pulse
1144
	movlw	0x00
1145
	btfsc	IRQ_TMP2, 7
1146
	movlw 0xff
1147
	movwf	MUL_A_L, BANKED
1148
	movlw	0x00
1149
	btfsc	IRQ_TMP2, 7
1150
	movlw 0x7f
1151
	movwf	MUL_A_H, BANKED
1152
 
1153
	rgoto	SIDSE_L_LFO_Wav_Cont
1154
 
1155
SIDSE_L_LFO_Wav_Cont
1156
 
1157
	;; scale by LFO depth
1158
	movlw	SID_Ix_LFOx_DEPTH
1159
	movff	PLUSW0, IRQ_TMP1
1160
 
1161
	;; depth can be modulated
1162
	;; calculate pointer to MOD target array -> FSR2
1163
	movf	SID_SE_ELEMENT_NUM, W, BANKED
1164
	addlw	(SID_MOD_TARG_LD1_L-SID_MOD_TARG_BASE)/3
1165
	mullw	3
1166
	lfsr	FSR1, SID_MOD_TARG_BASE
1167
	movf	PRODL, W
1168
	addlw	1		; select SID_MOD_TARG_LDx_H
1169
	addwf	FSR1L, F
1170
	movf	POSTINC1, W
1171
	addwf	IRQ_TMP1, F
1172
 
1173
	;; saturate
1174
	BRA_IFSET INDF1, 7, ACCESS, SIDSE_L_LFO_Depth_SatNeg
1175
SIDSE_L_LFO_DepthNeg_SatPos
1176
	movf	INDF1, W
1177
	bnz	SIDSE_L_LFO_DepthNeg_SatPos_Sat
1178
	bnc	SIDSE_L_LFO_DepthNeg_NoSat
1179
SIDSE_L_LFO_DepthNeg_SatPos_Sat
1180
	setf	IRQ_TMP1
1181
	rgoto	SIDSE_L_LFO_DepthNeg_Sat_Cont
1182
SIDSE_L_LFO_Depth_SatNeg
1183
	comf	INDF1, W
1184
	bnz	SIDSE_L_LFO_Depth_SatNeg_Sat
1185
	bc	SIDSE_L_LFO_DepthNeg_NoSat
1186
SIDSE_L_LFO_Depth_SatNeg_Sat
1187
	clrf	IRQ_TMP1
1188
	;; 	rgoto	SIDSE_L_LFO_DepthNeg_Sat_Cont
1189
SIDSE_L_LFO_DepthNeg_Sat_Cont
1190
SIDSE_L_LFO_DepthNeg_NoSat
1191
	movf	IRQ_TMP1, W
1192
	call	SIDSE_Hlp_ScaleDepth	; 15bit signed value in MUL_A_[LH], result in MUL_R_[12], uses IRQ_TMP1
1193
	rgoto	SIDSE_L_LFO_NotZero
1194
 
1195
SIDSE_L_LFO_Zero
1196
	clrf	MUL_R_1, BANKED
1197
	clrf	MUL_R_2, BANKED
1198
 
1199
SIDSE_L_LFO_NotZero
1200
	;; finally transfer result to SID_MOD_SRC_L_LFO1_[LH]
1201
	;; range: +/- 0x7fff
1202
	lfsr	FSR2, SID_MOD_SRC_L_LFO1_L
1203
	clrc
1204
	rlf	SID_SE_ELEMENT_NUM, W, BANKED
1205
	addwf	FSR2L, F
1206
	movff	MUL_R_1, POSTINC2
1207
	movff	MUL_R_2, POSTDEC2
1208
 
1209
SIDSE_L_LFO_End
1210
	return
1211
 
1212
 
1213
;; --------------------------------------------------------------------------
1214
;; This function handles the Envelopes
1215
;; IN: pointer to SID_Ix_L_ENVx_BASE in FSR0 (patch record)
1216
;;     pointer to SID_ENVx_BASE in FSR1
1217
;;     ENV number in SID_SE_ELEMENT_NUM
1218
;; --------------------------------------------------------------------------
1219
SIDSE_L_ENV
1220
	;; if clock sync enabled: only increment on clock events
1221
	movlw	SID_Ix_L_ENVx_MODE
1222
	BRA_IFCLR PLUSW0, SID_I_ENV_MODE_CLKSYNC, ACCESS, SIDSE_L_ENV_NoClkSync
1223
SIDSE_L_ENV_ClkSync
248 tk 1224
	BRA_IFCLR SID_SE_STATE, SID_SE_STATE_GLOBAL_CLK_EVENT, BANKED, SIDSE_L_ENV_ClkSync_Skp
1225
	movf	SID_SE_GLOBAL_CLK_CTR, W, BANKED
1226
	andlw	0x0f
1227
	bz	SIDSE_L_ENV_ClkSync_Cont
1228
SIDSE_L_ENV_ClkSync_Skp
1 tk 1229
	;; transfer current ENV counter into MIOS_PARAMETER[12]
1230
	movff	POSTINC1, MIOS_PARAMETER1
1231
	movff	POSTDEC1, MIOS_PARAMETER2
1232
	rgoto	SIDSE_L_ENV_Cont
1233
SIDSE_L_ENV_NoClkSync
1234
SIDSE_L_ENV_ClkSync_Cont
1235
 
1236
	;; branch depending on EG state
1237
	movlw	SID_ENVx_STATE
1238
	BRA_IFSET PLUSW1, SID_ENV_STATE_RELEASE2, ACCESS, SIDSE_L_ENV_Release2
1239
	BRA_IFSET PLUSW1, SID_ENV_STATE_RELEASE1, ACCESS, SIDSE_L_ENV_Release1
1240
	BRA_IFCLR PLUSW1, SID_ENV_STATE_ATTACK1, ACCESS, SIDSE_L_ENV_End
1241
	BRA_IFSET PLUSW1, SID_ENV_STATE_SUSTAIN, ACCESS, SIDSE_L_ENV_Sustain
1242
	BRA_IFSET PLUSW1, SID_ENV_STATE_DECAY2, ACCESS, SIDSE_L_ENV_Decay2
1243
	BRA_IFSET PLUSW1, SID_ENV_STATE_DECAY1, ACCESS, SIDSE_L_ENV_Decay1
1244
	BRA_IFSET PLUSW1, SID_ENV_STATE_ATTACK2, ACCESS, SIDSE_L_ENV_Attack2
1245
 
1246
SIDSE_L_ENV_Attack1
1247
 
1248
	;; temporary shift FSR1 to SID_ENVx_DELAY_CTR_L for easier handling
1249
	movlw	SID_ENVx_DELAY_CTR_L
1250
	addwf	FSR1L, F
1251
 
1252
	;; delay ENV so long 16bit delay counter != 0
1253
	movf	POSTINC1, W
1254
	iorwf	POSTDEC1, W
1255
	bz	SIDSE_L_ENV_Attack1_NoDelay
1256
SIDSE_L_ENV_Attack1_Delay
1257
	;; increment counter, set it to zero on overrun (no delay anymore)
1258
	movlw	SID_Ix_L_ENVx_DELAY
1259
	movff	PLUSW0, IRQ_TMP3; incrementer is the same like used for envelopes
1260
	movlw	0x80		; curve *must* be disabled!
1261
	call	SIDSE_Hlp_ENV_GetBendedValue	; incrementer in MIOS_PARAMETER[12]
1262
	movf	MIOS_PARAMETER1, W
1263
	addwf	POSTINC1, F
1264
	movf	MIOS_PARAMETER2, W
1265
	addwfc	POSTDEC1, F
1266
	bc	SIDSE_L_ENV_Attack1_DelayOv
1267
	rgoto	SIDSE_L_ENV_End
1268
SIDSE_L_ENV_Attack1_DelayOv
1269
	;; overrun: clear counter to disable delay
1270
	clrf	POSTINC1
1271
	clrf	POSTDEC1
1272
SIDSE_L_ENV_Attack1_NoDelay
1273
	movlw	-SID_ENVx_DELAY_CTR_L	; switch back to SID_ENVx_CTR_L
1274
	addwf	FSR1L, F
1275
 
1276
 
1277
	;; in attack1 phase we have to increase the EG counter
1278
	;; attack rate in IRQ_TMP3
1279
	movlw	SID_Ix_L_ENVx_ATTACK1
1280
	movf	PLUSW0, W
1281
	movwf	IRQ_TMP3
1282
	;; get final rate depending on curve setting
1283
	movlw	SID_Ix_L_ENVx_ATT_CURVE
1284
	movf	PLUSW0, W
1285
	call	SIDSE_Hlp_ENV_GetBendedValue
1286
	;; result: low byte in MIOS_PARAMETER1, high byte in MIOS_PARAMETER2
1287
	;; store final attack level in IRQ_TMP1
1288
	movlw	SID_Ix_L_ENVx_ATTLVL
1289
	movff	PLUSW0, IRQ_TMP1
1290
	;; increment counter
1291
	call	SIDSE_Hlp_ENV_IncrCtr
1292
	;; we've reached the level once the zero bit set
1293
	bnz	SIDSE_L_ENV_Cont
1294
 
1295
	;; switch to next phase
1296
	movlw	SID_ENV_STATE_ATTACK1
1297
	rcall	SIDSE_L_ENV_SetPhase
1298
 
1299
	rgoto	SIDSE_L_ENV_Cont
1300
 
1301
 
1302
SIDSE_L_ENV_Attack2
875 tk 1303
	;; in attack2 phase we have to increase the EG counter
1 tk 1304
	;; attack rate in IRQ_TMP3
1305
	movlw	SID_Ix_L_ENVx_ATTACK2
1306
	movff	PLUSW0, IRQ_TMP3
1307
	;; get final rate depending on curve setting
1308
	movlw	SID_Ix_L_ENVx_ATT_CURVE
1309
	movf	PLUSW0, W
1310
	call	SIDSE_Hlp_ENV_GetBendedValue
1311
	;; result: low byte in MIOS_PARAMETER1, high byte in MIOS_PARAMETER2
1312
	;; final attack level is 0xff
1313
	movlw	0xff
1314
	movwf	IRQ_TMP1
1315
	;; increment counter
1316
	call	SIDSE_Hlp_ENV_IncrCtr
1317
	;; we've reached the level once the zero bit set
1318
	bnz	SIDSE_L_ENV_Cont
1319
 
1320
	;; switch to next phase
1321
	movlw	SID_ENV_STATE_ATTACK2
1322
	rcall	SIDSE_L_ENV_SetPhase
1323
 
1324
	rgoto	SIDSE_L_ENV_Cont
1325
 
1326
 
1327
SIDSE_L_ENV_Decay1
1328
	;; in decay1 phase we have to increase/decrease the EG counter depending on the current level
1329
	;; decay1 rate in IRQ_TMP3
1330
	movlw	SID_Ix_L_ENVx_DECAY1
1331
	movff	PLUSW0, IRQ_TMP3
1332
	;; get final rate depending on curve setting
1333
	movlw	SID_Ix_L_ENVx_DEC_CURVE
1334
	movf	PLUSW0, W
1335
	call	SIDSE_Hlp_ENV_GetBendedValue
1336
	;; result: low byte in MIOS_PARAMETER1, high byte in MIOS_PARAMETER2
1337
	;; store final decay level in IRQ_TMP1
1338
	movlw	SID_Ix_L_ENVx_DECLVL
1339
	movff	PLUSW0, IRQ_TMP1
1340
	;; incr/decr counter
1341
	call	SIDSE_Hlp_ENV_IncrDecrCtr
1342
	;; we've reached the level once the zero bit set
1343
	bnz	SIDSE_L_ENV_Cont
1344
 
1345
	;; switch to next phase
1346
	movlw	SID_ENV_STATE_DECAY1
1347
	rcall	SIDSE_L_ENV_SetPhase
1348
 
1349
	rgoto	SIDSE_L_ENV_Cont
1350
 
1351
 
1352
SIDSE_L_ENV_Decay2
1353
	;; in decay2 phase we have to increase/decrease the EG counter depending on the current level
1354
	;; decay2 rate in WREG
1355
	movlw	SID_Ix_L_ENVx_DECAY2
1356
	movff	PLUSW0, IRQ_TMP3
1357
	;; get final rate depending on curve setting
1358
	movlw	SID_Ix_L_ENVx_DEC_CURVE
1359
	movf	PLUSW0, W
1360
	call	SIDSE_Hlp_ENV_GetBendedValue
1361
	;; result: low byte in MIOS_PARAMETER1, high byte in MIOS_PARAMETER2
1362
	;; store final sustain in IRQ_TMP1
1363
	movlw	SID_Ix_L_ENVx_SUSTAIN
1364
	movff	PLUSW0, IRQ_TMP1
1365
	;; incr/decr counter
1366
	call	SIDSE_Hlp_ENV_IncrDecrCtr
1367
	;; we've reached the level once the zero bit set
1368
	bnz	SIDSE_L_ENV_Cont
1369
 
1370
	;; propagate sustain phase to trigger matrix (using FSR2 as working pointer)
1371
	movf	SID_SE_ELEMENT_NUM, W, BANKED
1372
	mullw	3
1373
	lfsr	FSR2, SID_PATCH_BUFFER_SHADOW + SID_Ix_L_TRG_E1S_BASE
1374
	movf	PRODL, W
1375
	addwf	FSR2L, F
1376
	movf	POSTINC2, W
1377
	iorwf	SID_SE_TRG_EVNT_L, F, BANKED
1378
	movf	POSTINC2, W
1379
	iorwf	SID_SE_TRG_EVNT_H, F, BANKED
1380
	movf	POSTINC2, W
1381
	iorwf	SID_SE_TRG_EVNT_U, F, BANKED
1382
 
1383
	;; switch to next phase
1384
	movlw	SID_ENV_STATE_DECAY2
1385
	rcall	SIDSE_L_ENV_SetPhase
1386
 
1387
	movlw	SID_ENVx_STATE
1388
	BRA_IFCLR PLUSW1, SID_ENV_STATE_SUSTAIN, ACCESS, SIDSE_L_ENV_Cont
1389
 
1390
SIDSE_L_ENV_Sustain
1391
	;; write sustain value into counter (again)
1392
	movlw	SID_Ix_L_ENVx_SUSTAIN
1393
	movff	PLUSW0, MIOS_PARAMETER2
1394
	clrf	MIOS_PARAMETER1
1395
 
1396
	;; loop in this phase
1397
	movlw	SID_ENV_STATE_SUSTAIN
1398
	rcall	SIDSE_L_ENV_SetPhase
1399
 
1400
	rgoto	SIDSE_L_ENV_Cont
1401
 
1402
 
1403
SIDSE_L_ENV_Release1
1404
	;; in release phase we have to decrease the EG counter until it reaches the sustain level
1405
	;; release rate in WREG
1406
	movlw	SID_Ix_L_ENVx_RELEASE1
1407
	movff	PLUSW0, IRQ_TMP3
1408
	;; get release rate depending on curve setting
1409
	movlw	SID_Ix_L_ENVx_REL_CURVE
1410
	movf	PLUSW0, W
1411
	call	SIDSE_Hlp_ENV_GetBendedValue
1412
	;; result: low byte in MIOS_PARAMETER1, high byte in MIOS_PARAMETER2
1413
	;; store release level in IRQ_TMP1
1414
	movlw	SID_Ix_L_ENVx_RELLVL
1415
	movff	PLUSW0, IRQ_TMP1
1416
	;; incr/decr counter
1417
	call	SIDSE_Hlp_ENV_IncrDecrCtr
1418
 
1419
	;; we've reached the level once the zero bit set
1420
	bnz	SIDSE_L_ENV_Cont
1421
 
1422
	;; switch to next phase
1423
	movlw	SID_ENV_STATE_RELEASE1
1424
	rcall	SIDSE_L_ENV_SetPhase
1425
 
1426
	rgoto	SIDSE_L_ENV_Cont
1427
 
1428
SIDSE_L_ENV_Release2
1429
	;; in the final release phase we have to decrease the EG counter until it reaches 0
1430
	;; release rate in WREG
1431
	movlw	SID_Ix_L_ENVx_RELEASE2
1432
	movff	PLUSW0, IRQ_TMP3
1433
	;; get release rate depending on curve setting
1434
	movlw	SID_Ix_L_ENVx_REL_CURVE
1435
	movf	PLUSW0, W
1436
	call	SIDSE_Hlp_ENV_GetBendedValue
1437
	;; target level: 0
1438
	clrf	IRQ_TMP1
1439
	;; decr counter
1440
	call	SIDSE_Hlp_ENV_DecrCtr
1441
 
1442
	;; switch to next phase (if required)
1443
	movlw	SID_ENV_STATE_RELEASE2
1444
	rcall	SIDSE_L_ENV_SetPhase
1445
 
1446
	;; 	rgoto	SIDSE_L_ENV_Cont
1447
 
1448
SIDSE_L_ENV_Cont
1449
	;; copy MIOS_PARAMETER[12] to SID_ENVx_CTR_[LH]
1450
	movff	MIOS_PARAMETER1, POSTINC1
1451
	movff	MIOS_PARAMETER2, POSTDEC1
1452
 
1453
	clrc
1454
	rrf	MIOS_PARAMETER2, W
1455
	movwf	MUL_A_H, BANKED
1456
	rrf	MIOS_PARAMETER1, W
1457
	movwf	MUL_A_L, BANKED
1458
 
1459
	;; skip ENV mapping if result is zero (write zero directly into registers)
1460
	movf	MIOS_PARAMETER1, W
1461
	iorwf	MIOS_PARAMETER2, W
1462
	bz	SIDSE_L_ENV_Cont_Zero
1463
 
1464
	;; scale by ENV depth (skip if depth is zero)
1465
	movlw	SID_Ix_L_ENVx_DEPTH
1466
	movf	PLUSW0, W
1467
	xorlw	0x80
1468
	bz	SIDSE_L_ENV_Cont_Zero
1469
	xorlw	0x80
1470
	call	SIDSE_Hlp_ScaleDepth	; 15bit signed value in MUL_A_[LH], result in MUL_R_[12], uses IRQ_TMP1
1471
	rgoto	SIDSE_L_ENV_Cont_NotZero
1472
 
1473
SIDSE_L_ENV_Cont_Zero
1474
	clrf	MUL_R_1, BANKED	; result is zero - optimized
1475
	clrf	MUL_R_2, BANKED
1476
 
1477
SIDSE_L_ENV_Cont_NotZero
1478
	;; finally transfer result to SID_MOD_SRC_L_ENVx_VALUE_[LH]
1479
	;; range: +/- 0x7fff
1480
	lfsr	FSR2, SID_MOD_SRC_L_ENV1_L
1481
	clrc
1482
	rlf	SID_SE_ELEMENT_NUM, W, BANKED
1483
	addwf	FSR2L, F
1484
	movff	MUL_R_1, POSTINC2
1485
	movff	MUL_R_2, POSTDEC2
1486
 
1487
SIDSE_L_ENV_End
1488
	return
1489
 
1490
 
1491
;; --------------------------------------------------------------------------
1492
;; This function handles the Modulation Matrix
1493
;; IN: pointer to SID_Ix_MODx_BASE in FSR0 (patch record)
1494
;;     MOD number in SID_SE_ELEMENT_NUM
1495
;; --------------------------------------------------------------------------
1496
SIDSE_L_MOD
1497
	;; skip if depth is zero
1498
	movlw	SID_Ix_MODx_DEPTH
1499
	movf	PLUSW0, W
1500
	xorlw	0x80
1501
	skpnz
1502
	rgoto	SIDSE_L_MOD_End
1503
 
1504
	;; copy first source to SID_SE_MOD_SRC1_[LH]
1505
	movlw	SID_Ix_MODx_SRC1
1506
	movf	PLUSW0, W
1507
	bz	SIDSE_L_MOD_Src1_Disabled
1508
	BRA_IFSET WREG, 7, ACCESS, SIDSE_L_MOD_Src1_Const
1509
SIDSE_L_MOD_Src1
1510
	lfsr	FSR2, SID_MOD_SRC_BASE
1511
	addlw	-1
1512
	rlf	WREG, W
1513
	andlw	0xfe
1514
	addlw	1
1515
	addwf	FSR2L, F
1516
	clrc
1517
	rrf	POSTDEC2, W
1518
	movwf	SID_SE_MOD_SRC1_H, BANKED
1519
	rrf	INDF2, W
1520
	movwf	SID_SE_MOD_SRC1_L, BANKED
1521
	btfsc	SID_SE_MOD_SRC1_H, 6, BANKED
1522
	bsf	SID_SE_MOD_SRC1_H, 7, BANKED
1523
	;; range: +/- 0x3fff
1524
	rgoto	SIDSE_L_MOD_Src1_Cont
1525
 
1526
SIDSE_L_MOD_Src1_Const
1527
	;; range 0x00..0x7f -> +0x0000..0x03f80
1528
	rrf	WREG, W
1529
	andlw	0x3f
1530
	movwf	SID_SE_MOD_SRC1_H, BANKED
1531
	clrf	SID_SE_MOD_SRC1_L, BANKED
1532
	rrf	SID_SE_MOD_SRC1_L, F, BANKED
1533
	rgoto	SIDSE_L_MOD_Src1_Cont
1534
 
1535
SIDSE_L_MOD_Src1_Disabled
1536
	clrf	SID_SE_MOD_SRC1_L, BANKED
1537
	clrf	SID_SE_MOD_SRC1_H, BANKED
1538
	;; 	rgoto	SIDSE_L_MOD_Src1_Cont
1539
SIDSE_L_MOD_Src1_Cont
1540
 
1541
	;; copy second source to SID_SE_MOD_SRC2_[LH]
1542
	movlw	SID_Ix_MODx_SRC2
1543
	movf	PLUSW0, W
1544
	bz	SIDSE_L_MOD_Src2_Disabled
1545
	BRA_IFSET WREG, 7, ACCESS, SIDSE_L_MOD_Src2_Const
1546
SIDSE_L_MOD_Src2
1547
	lfsr	FSR2, SID_MOD_SRC_BASE
1548
	addlw	-1
1549
	rlf	WREG, W
1550
	andlw	0xfe
1551
	addlw	1
1552
	addwf	FSR2L, F
1553
	clrc
1554
	rrf	POSTDEC2, W
1555
	movwf	SID_SE_MOD_SRC2_H, BANKED
1556
	rrf	INDF2, W
1557
	movwf	SID_SE_MOD_SRC2_L, BANKED
1558
	btfsc	SID_SE_MOD_SRC2_H, 6, BANKED
1559
	bsf	SID_SE_MOD_SRC2_H, 7, BANKED
1560
	;; range: +/- 0x3fff
1561
	rgoto	SIDSE_L_MOD_Src2_Cont
1562
 
1563
SIDSE_L_MOD_Src2_Const
1564
	;; range 0x00..0x7f -> +0x0000..0x03f80
1565
	rrf	WREG, W
1566
	andlw	0x3f
1567
	movwf	SID_SE_MOD_SRC2_H, BANKED
1568
	clrf	SID_SE_MOD_SRC2_L, BANKED
1569
	rrf	SID_SE_MOD_SRC2_L, F, BANKED
1570
	rgoto	SIDSE_L_MOD_Src2_Cont
1571
 
1572
SIDSE_L_MOD_Src2_Disabled
1573
	clrf	SID_SE_MOD_SRC2_L, BANKED
1574
	clrf	SID_SE_MOD_SRC2_H, BANKED
1575
	;; 	rgoto	SIDSE_L_MOD_Src2_Cont
1576
SIDSE_L_MOD_Src2_Cont
1577
 
1578
	;; apply selected operation
1579
	movlw	SID_Ix_MODx_OP
1580
	movf	PLUSW0, W
1581
	andlw	0x0f
1582
	JUMPTABLE_2BYTES_UNSECURE
1583
	rgoto	SIDSE_L_MOD_OP_0
1584
	rgoto	SIDSE_L_MOD_OP_1
1585
	rgoto	SIDSE_L_MOD_OP_2
1586
	rgoto	SIDSE_L_MOD_OP_3
1587
	rgoto	SIDSE_L_MOD_OP_4
1588
	rgoto	SIDSE_L_MOD_OP_5
1589
	rgoto	SIDSE_L_MOD_OP_6
1590
	rgoto	SIDSE_L_MOD_OP_7
1591
	rgoto	SIDSE_L_MOD_OP_8
1592
	rgoto	SIDSE_L_MOD_OP_9
1593
	rgoto	SIDSE_L_MOD_OP_10
1594
	rgoto	SIDSE_L_MOD_OP_11
1595
	rgoto	SIDSE_L_MOD_OP_12
1596
	rgoto	SIDSE_L_MOD_OP_13
1597
	rgoto	SIDSE_L_MOD_OP_14
1598
	rgoto	SIDSE_L_MOD_OP_15
1599
 
1600
SIDSE_L_MOD_OP_0	; disabled
1601
	clrf	MUL_A_L, BANKED
1602
	clrf	MUL_A_H, BANKED
1603
	rgoto	SIDSE_L_MOD_OP_Cont
1604
 
1605
SIDSE_L_MOD_OP_1	; SRC1 only
1606
	movff	SID_SE_MOD_SRC1_L, MUL_A_L
1607
	movff	SID_SE_MOD_SRC1_H, MUL_A_H
1608
	rgoto	SIDSE_L_MOD_OP_Cont
1609
 
1610
SIDSE_L_MOD_OP_2	; SRC2 only
1611
	movff	SID_SE_MOD_SRC2_L, MUL_A_L
1612
	movff	SID_SE_MOD_SRC2_H, MUL_A_H
1613
	rgoto	SIDSE_L_MOD_OP_Cont
1614
 
1615
SIDSE_L_MOD_OP_3	; SRC1+SRC2
1616
	movf	SID_SE_MOD_SRC1_L, W, BANKED
1617
	addwf	SID_SE_MOD_SRC2_L, W, BANKED
1618
	movwf	MUL_A_L, BANKED
1619
	movf	SID_SE_MOD_SRC1_H, W, BANKED
1620
	addwfc	SID_SE_MOD_SRC2_H, W, BANKED
1621
	movwf	MUL_A_H, BANKED
1622
	rgoto	SIDSE_L_MOD_OP_Cont
1623
 
1624
SIDSE_L_MOD_OP_4	; SRC1-SRC2
1625
	movf	SID_SE_MOD_SRC1_L, W, BANKED
1626
	subwf	SID_SE_MOD_SRC2_L, W, BANKED
1627
	movwf	MUL_A_L, BANKED
1628
	movf	SID_SE_MOD_SRC1_H, W, BANKED
1629
	subwfb	SID_SE_MOD_SRC2_H, W, BANKED
1630
	movwf	MUL_A_H, BANKED
1631
	rgoto	SIDSE_L_MOD_OP_Cont
1632
 
1633
SIDSE_L_MOD_OP_5	; SRC1*SRC2
1634
	clrc
1635
	rlf	SID_SE_MOD_SRC1_L, W, BANKED
1636
	movwf	MUL_A_L, BANKED
1637
	rlf	SID_SE_MOD_SRC1_H, W, BANKED
1638
	movwf	MUL_A_H, BANKED
1639
 
1640
	clrc
1641
	rlf	SID_SE_MOD_SRC2_L, W, BANKED
1642
	movwf	MUL_B_L, BANKED
1643
	rlf	SID_SE_MOD_SRC2_H, W, BANKED
1644
	movwf	MUL_B_H, BANKED
1645
 
1646
	call	MATH_MUL16_16_SIGNED
1647
 
1648
	movff	MUL_R_2, MUL_A_L
1649
	movff	MUL_R_3, MUL_A_H
1650
	rgoto	SIDSE_L_MOD_OP_Cont
1651
 
1652
SIDSE_L_MOD_OP_6	; XOR
1653
	movf	SID_SE_MOD_SRC1_L, W, BANKED
1654
	xorwf	SID_SE_MOD_SRC2_L, W, BANKED
1655
	movwf	MUL_A_L, BANKED
1656
	movf	SID_SE_MOD_SRC1_H, W, BANKED
1657
	xorwf	SID_SE_MOD_SRC2_H, W, BANKED
1658
	movwf	MUL_A_H, BANKED
1659
	rgoto	SIDSE_L_MOD_OP_Cont
1660
 
1661
SIDSE_L_MOD_OP_7	; OR
1662
	movf	SID_SE_MOD_SRC1_L, W, BANKED
1663
	iorwf	SID_SE_MOD_SRC2_L, W, BANKED
1664
	movwf	MUL_A_L, BANKED
1665
	movf	SID_SE_MOD_SRC1_H, W, BANKED
1666
	iorwf	SID_SE_MOD_SRC2_H, W, BANKED
1667
	movwf	MUL_A_H, BANKED
1668
	rgoto	SIDSE_L_MOD_OP_Cont
1669
 
1670
SIDSE_L_MOD_OP_8	; AND
1671
	movf	SID_SE_MOD_SRC1_L, W, BANKED
1672
	andwf	SID_SE_MOD_SRC2_L, W, BANKED
1673
	movwf	MUL_A_L, BANKED
1674
	movf	SID_SE_MOD_SRC1_H, W, BANKED
1675
	andwf	SID_SE_MOD_SRC2_H, W, BANKED
1676
	movwf	MUL_A_H, BANKED
1677
	rgoto	SIDSE_L_MOD_OP_Cont
1678
 
1679
SIDSE_L_MOD_OP_9	; Min
1680
	;; check if SRC1 < SRC2
1681
SIDSE_L_MOD_OP_9_CmpH
1682
	movf	SID_SE_MOD_SRC2_H, W, BANKED	; signed value comparison
1683
	xorlw	0x80
1684
	movwf	IRQ_TMP1
1685
	movf	SID_SE_MOD_SRC1_H, W, BANKED
1686
	xorlw	0x80
1687
	subwf	IRQ_TMP1, W
1688
	bnz	SIDSE_L_MOD_OP_9_SkipCmpL
1689
SIDSE_L_MOD_OP_9_CmpL
1690
	movf	SID_SE_MOD_SRC1_L, W, BANKED
1691
	subwf	SID_SE_MOD_SRC2_L, W, BANKED
1692
SIDSE_L_MOD_OP_9_SkipCmpL
1693
	bc	SIDSE_L_MOD_OP_1	; SRC1 is less -> SRC1 only
1694
	rgoto	SIDSE_L_MOD_OP_2	; SRC2 is less -> SRC2 only
1695
 
1696
SIDSE_L_MOD_OP_10	; Max
1697
	;; check if SRC1 > SRC2
1698
SIDSE_L_MOD_OP_10_CmpH
1699
	movf	SID_SE_MOD_SRC2_H, W, BANKED	; signed value comparison
1700
	xorlw	0x80
1701
	movwf	IRQ_TMP1
1702
	movf	SID_SE_MOD_SRC1_H, W, BANKED
1703
	xorlw	0x80
1704
	subwf	IRQ_TMP1, W
1705
	bnz	SIDSE_L_MOD_OP_10_SkipCmpL
1706
SIDSE_L_MOD_OP_10_CmpL
1707
	movf	SID_SE_MOD_SRC1_L, W, BANKED
1708
	subwf	SID_SE_MOD_SRC2_L, W, BANKED
1709
SIDSE_L_MOD_OP_10_SkipCmpL
1710
	bc	SIDSE_L_MOD_OP_2	; SRC2 is greater -> SRC2 only
1711
	rgoto	SIDSE_L_MOD_OP_1	; SRC1 is greater -> SRC1 only
1712
 
1713
SIDSE_L_MOD_OP_11
1714
	;; check if SRC1 < SRC2
1715
SIDSE_L_MOD_OP_11_CmpH
1716
	movf	SID_SE_MOD_SRC2_H, W, BANKED	; signed value comparison
1717
	xorlw	0x80
1718
	movwf	IRQ_TMP1
1719
	movf	SID_SE_MOD_SRC1_H, W, BANKED
1720
	xorlw	0x80
1721
	subwf	IRQ_TMP1, W
1722
	bnz	SIDSE_L_MOD_OP_11_SkipCmpL
1723
SIDSE_L_MOD_OP_11_CmpL
1724
	movf	SID_SE_MOD_SRC1_L, W, BANKED
1725
	subwf	SID_SE_MOD_SRC2_L, W, BANKED
1726
SIDSE_L_MOD_OP_11_SkipCmpL
1727
	bc	SIDSE_L_MOD_OP_Cont_High	; SRC1 is less -> high value
1728
	rgoto	SIDSE_L_MOD_OP_Cont_Low	; SRC2 is less -> low value
1729
 
1730
SIDSE_L_MOD_OP_12
1731
	;; check if SRC1 > SRC2
1732
SIDSE_L_MOD_OP_12_CmpH
1733
	movf	SID_SE_MOD_SRC2_H, W, BANKED	; signed value comparison
1734
	xorlw	0x80
1735
	movwf	IRQ_TMP1
1736
	movf	SID_SE_MOD_SRC1_H, W, BANKED
1737
	xorlw	0x80
1738
	subwf	IRQ_TMP1, W
1739
	bnz	SIDSE_L_MOD_OP_12_SkipCmpL
1740
SIDSE_L_MOD_OP_12_CmpL
1741
	movf	SID_SE_MOD_SRC1_L, W, BANKED
1742
	subwf	SID_SE_MOD_SRC2_L, W, BANKED
1743
SIDSE_L_MOD_OP_12_SkipCmpL
1744
	bc	SIDSE_L_MOD_OP_Cont_Low	; SRC1 is less -> low value
1745
	rgoto	SIDSE_L_MOD_OP_Cont_High	; SRC2 is less -> high value
1746
 
1747
SIDSE_L_MOD_OP_13
1748
	;; check if SRC1 = SRC2
1749
	;; (only high bytes are checked for lower granularity)
1750
	movf	SID_SE_MOD_SRC2_H, W, BANKED
1751
	xorwf	SID_SE_MOD_SRC1_H, W, BANKED
1752
	bz	SIDSE_L_MOD_OP_Cont_High	; high bytes equal -> high value
1753
	rgoto	SIDSE_L_MOD_OP_Cont_Low	; high bytes not equal -> low value
1754
 
1755
SIDSE_L_MOD_OP_14
1756
	;; S&H - SRC1 will be sampled whenever SRC2 changes from a negative to a positive value
1757
 
1758
	;; determine OR/AND mask for MOD element -> IRQ_TMP1
1759
	movf	SID_SE_ELEMENT_NUM, W, BANKED
1760
	call	MIOS_HLP_GetBitORMask
1761
	movwf	IRQ_TMP1
1762
 
1763
	;; determine if SRC2 is negative or positive - store NEG flag at correct bit position in IRQ_TMP2
1764
	btfss	SID_SE_MOD_SRC2_H, 7, BANKED
1765
	movlw	0x00
1766
	movwf	IRQ_TMP2
1767
 
1768
	;; check for 0 transition, if not: forward old value (HOLD)
1769
	movf	SID_SE_MOD_TRANSITION, W, BANKED
1770
	andwf	IRQ_TMP1, W
1771
	xorwf	IRQ_TMP2, W
1772
	bz	SIDSE_L_MOD_OP_14_Hold
1773
 
1774
SIDSE_L_MOD_OP_14_Sample
1775
	;; store new NEG flag
1776
	comf	IRQ_TMP1, W
1777
	andwf	SID_SE_MOD_TRANSITION, F, BANKED
1778
	movf	IRQ_TMP2, W
1779
	iorwf	SID_SE_MOD_TRANSITION, F, BANKED
1780
 
1781
	;; still hold when we are in negative range now
1782
	;; (only sample on negative->positive transition)
1783
	movf	IRQ_TMP2, W
1784
	bnz	SIDSE_L_MOD_OP_14_Hold
1785
 
1786
	;; take new SRC1 value
1787
	rgoto	SIDSE_L_MOD_OP_1
1788
 
1789
SIDSE_L_MOD_OP_14_Hold
1790
	;; take old MOD value
1791
	lfsr	FSR2, SID_MOD_SRC_BASE
1792
	clrc
1793
	rlf	SID_SE_ELEMENT_NUM, W, BANKED
1794
	addlw	SID_MOD_SRC_L_MOD1_L-SID_MOD_SRC_BASE
1795
	addwf	FSR2L, F
1796
	movff	POSTINC2, MUL_A_L
1797
	movff	POSTINC2, MUL_A_H
1798
 
1799
	rgoto	SIDSE_L_MOD_OP_Cont
1800
 
1801
SIDSE_L_MOD_OP_15	; reserved
1802
	rgoto	SIDSE_L_MOD_OP_0
1803
 
1804
 
1805
SIDSE_L_MOD_OP_Cont_High		; constant high value
1806
	setf	MUL_A_L, BANKED
1807
	movlw	0x7f
1808
	movwf	MUL_A_H, BANKED
1809
	rgoto	SIDSE_L_MOD_OP_Cont
1810
 
1811
SIDSE_L_MOD_OP_Cont_Low		; constant low value
1812
	clrf	MUL_A_L, BANKED
228 tk 1813
#if 0
1 tk 1814
	movlw	0x80
1815
	movwf	MUL_A_H, BANKED
228 tk 1816
#else
1817
	clrf	MUL_A_H, BANKED	; TK: 0 instead of full negative value is more useful
1818
#endif
1 tk 1819
	;; 	rgoto	SIDSE_L_MOD_OP_Cont
1820
 
1821
SIDSE_L_MOD_OP_Cont
1822
 
1823
	;; store in modulator source array for feedbacks
1824
	;; use value w/o depth, this has two advantages:
1825
	;; - maximum resolution when forwarding the data value
1826
	;; - original MOD value can be taken for sample&hold feature
1827
	;; but it has also a disadvantage:
1828
	;; - the user could think it is a bug when depth doesn't affect the feedback MOD value...
1829
	lfsr	FSR2, SID_MOD_SRC_BASE
1830
	clrc
1831
	rlf	SID_SE_ELEMENT_NUM, W, BANKED
1832
	addlw	SID_MOD_SRC_L_MOD1_L-SID_MOD_SRC_BASE
1833
	addwf	FSR2L, F
1834
	movff	MUL_A_L, POSTINC2
1835
	movff	MUL_A_H, POSTINC2
1836
 
1837
	;; skip if modulation result is zero
1838
	movf	MUL_A_L, W, BANKED
1839
	iorwf	MUL_A_H, W, BANKED
1840
	skpnz
1841
	rgoto	SIDSE_L_MOD_End
1842
 
1843
	;; scale by MOD depth		; (zero check already at top of MOD function)
1844
	movlw	SID_Ix_MODx_DEPTH
1845
	movf	PLUSW0, W
1846
	call	SIDSE_Hlp_ScaleDepth	; 15bit signed value in MUL_A_[LH], result in MUL_R_[12], uses IRQ_TMP1
1847
 
1848
	;; store in METER_VALUES array for optional visualisation on the modulation matrix
835 tk 1849
#if !DEFAULT_SAMMICHSID_CS
828 tk 1850
	;; not if sammichSID display mode is selected
1 tk 1851
	movff	MUL_R_2, MIOS_PARAMETER1
1852
	movf	SID_SE_ELEMENT_NUM, W, BANKED
1853
	call	CS_MENU_MATRIX_MeterSet
1854
	;; uses FSR1 !!!
828 tk 1855
#endif
1 tk 1856
 
1857
	;; multiply by two (to allow full range sweeps)
1858
	rlf	MUL_R_1, F, BANKED
1859
	rlf	MUL_R_2, F, BANKED
1860
	rlf	MUL_R_3, F, BANKED
1861
 
1862
	;; copy to MOD result registers
1863
	movff	MUL_R_1, SID_SE_MOD_RES1_L
1864
	movff	MUL_R_2, SID_SE_MOD_RES1_H
1865
	movff	MUL_R_3, SID_SE_MOD_RES1_U
1866
	movff	MUL_R_1, SID_SE_MOD_RES2_L
1867
	movff	MUL_R_2, SID_SE_MOD_RES2_H
1868
	movff	MUL_R_3, SID_SE_MOD_RES2_U
1869
 
1870
	;; invert result1 if requested
1871
	movlw	SID_Ix_MODx_OP
1872
	BRA_IFCLR PLUSW0, 6, ACCESS, SIDSE_L_MOD_OP_Res1_NoInv
1873
SIDSE_L_MOD_OP_Res1_Inv
1874
	comf	SID_SE_MOD_RES1_L, F, BANKED
1875
	comf	SID_SE_MOD_RES1_H, F, BANKED
1876
	comf	SID_SE_MOD_RES1_U, F, BANKED
1877
	incf	SID_SE_MOD_RES1_L, F, BANKED
1878
	skpnz
1879
	incf	SID_SE_MOD_RES1_H, F, BANKED
1880
	skpnz
1881
	incf	SID_SE_MOD_RES1_U, F, BANKED
1882
SIDSE_L_MOD_OP_Res1_NoInv
1883
 
1884
	;; invert result2 if requested
1885
	movlw	SID_Ix_MODx_OP
1886
	BRA_IFCLR PLUSW0, 7, ACCESS, SIDSE_L_MOD_OP_Res2_NoInv
1887
SIDSE_L_MOD_OP_Res2_Inv
1888
	comf	SID_SE_MOD_RES2_L, F, BANKED
1889
	comf	SID_SE_MOD_RES2_H, F, BANKED
1890
	comf	SID_SE_MOD_RES2_U, F, BANKED
1891
	incf	SID_SE_MOD_RES2_L, F, BANKED
1892
	skpnz
1893
	incf	SID_SE_MOD_RES2_H, F, BANKED
1894
	skpnz
1895
	incf	SID_SE_MOD_RES2_U, F, BANKED
1896
SIDSE_L_MOD_OP_Res2_NoInv
1897
 
1898
	;; add result to modulation target array
1899
	movlw	SID_Ix_MODx_TARG_X1
1900
	movf	PLUSW0, W
1901
	bz	SIDSE_L_MOD_Targ1_Disabled
1902
SIDSE_L_MOD_Targ1
1903
	lfsr	FSR2, SID_MOD_TARG_BASE
1904
	addlw	-1
1905
	mullw	3
1906
	lfsr	FSR2, SID_MOD_TARG_BASE
1907
	movf	PRODL, W
1908
	andlw	0x7f		; avoid access outside target array!
1909
	addwf	FSR2L, F
1910
	rcall	SIDSE_L_MOD_Hlp_AddTarget1
1911
SIDSE_L_MOD_Targ1_Disabled
1912
 
1913
	;; add result to modulation target array
1914
	movlw	SID_Ix_MODx_TARG_X2
1915
	movf	PLUSW0, W
1916
	bz	SIDSE_L_MOD_Targ2_Disabled
1917
SIDSE_L_MOD_Targ2
1918
	addlw	-1
1919
	mullw	3
1920
	lfsr	FSR2, SID_MOD_TARG_BASE
1921
	movf	PRODL, W
1922
	andlw	0x7f		; avoid access outside target array!
1923
	addwf	FSR2L, F
1924
	rcall	SIDSE_L_MOD_Hlp_AddTarget2
1925
SIDSE_L_MOD_Targ2_Disabled
1926
 
1927
	;; add to additional SIDL/R targets
1928
 
1929
SIDSE_L_MOD_COPYTARG_MACRO MACRO func, SID_MOD_TARG_x, flag
1930
	LOCAL	SIDSE_L_MOD_COPYTARG_MACRO_Skip
1931
	BRA_IFCLR IRQ_TMP1, flag, ACCESS, SIDSE_L_MOD_COPYTARG_MACRO_Skip
1932
	lfsr	FSR2, SID_MOD_TARG_x
1933
	rcall	func
1934
SIDSE_L_MOD_COPYTARG_MACRO_Skip
1935
	ENDM
1936
 
1937
 
1938
	movlw	SID_Ix_MODx_TARG_L
1939
	movff	PLUSW0, IRQ_TMP1
1940
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget1, SID_MOD_TARG_PITCH1_L, 0
1941
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget1, SID_MOD_TARG_PITCH2_L, 1
1942
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget1, SID_MOD_TARG_PITCH3_L, 2
1943
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget1, SID_MOD_TARG_PW1_L, 3
1944
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget1, SID_MOD_TARG_PW2_L, 4
1945
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget1, SID_MOD_TARG_PW3_L, 5
1946
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget1, SID_MOD_TARG_FIL1_L, 6
1947
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget1, SID_MOD_TARG_VOL1_L, 7
1948
 
1949
	movlw	SID_Ix_MODx_TARG_R
1950
	movff	PLUSW0, IRQ_TMP1
1951
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget2, SID_MOD_TARG_PITCH4_L, 0
1952
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget2, SID_MOD_TARG_PITCH5_L, 1
1953
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget2, SID_MOD_TARG_PITCH6_L, 2
1954
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget2, SID_MOD_TARG_PW4_L, 3
1955
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget2, SID_MOD_TARG_PW5_L, 4
1956
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget2, SID_MOD_TARG_PW6_L, 5
1957
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget2, SID_MOD_TARG_FIL2_L, 6
1958
	SIDSE_L_MOD_COPYTARG_MACRO SIDSE_L_MOD_Hlp_AddTarget2, SID_MOD_TARG_VOL2_L, 7
1959
 
1960
SIDSE_L_MOD_End
1961
	return
1962
 
1963
;; help function which is used to add the result to a specific target (pointer in FSR2)
1964
SIDSE_L_MOD_Hlp_AddTarget1
1965
	movf	SID_SE_MOD_RES1_L, W, BANKED
1966
	addwf	POSTINC2, F
1967
	movf	SID_SE_MOD_RES1_H, W, BANKED
1968
	addwfc	POSTINC2, F
1969
	movf	SID_SE_MOD_RES1_U, W, BANKED
1970
	addwfc	POSTINC2, F
1971
	return
1972
 
1973
SIDSE_L_MOD_Hlp_AddTarget2
1974
	movf	SID_SE_MOD_RES2_L, W, BANKED
1975
	addwf	POSTINC2, F
1976
	movf	SID_SE_MOD_RES2_H, W, BANKED
1977
	addwfc	POSTINC2, F
1978
	movf	SID_SE_MOD_RES2_U, W, BANKED
1979
	addwfc	POSTINC2, F
1980
	return
1981
 
1982
 
1983
;; --------------------------------------------------------------------------
1984
;; Help Function for SIDSE_L_ENV for switching to a new phase
1985
;; Takes also the loop point into account
1986
;; IN:  pointer to SID_Ix_L_ENVx_BASE in FSR0 (patch record)
1987
;;      pointer to SID_ENVx_BASE in FSR1
1988
;;      current loop point in WREG (corresponds to SID_ENV_STATE_XXX flag)
1989
;; OUT:	changed SID_ENVx_STATE
1990
;; --------------------------------------------------------------------------
1991
SIDSE_L_ENV_SetPhase
1992
	movwf	PRODL		; temporary store phase number in PRODL and PRODH
1993
	movwf	PRODH		; (for sustain check)
1994
 
1995
	;; check for loop point
1996
	movlw	SID_Ix_L_ENVx_MODE
1997
	swapf	PLUSW0, W
1998
	andlw	0x07
1999
	addlw	-1
2000
	xorwf	PRODL, W	; check with current phase
2001
	bnz	SIDSE_L_ENV_SetPhase_NoLoop
2002
SIDSE_L_ENV_SetPhase_Loop
2003
	movlw	SID_Ix_L_ENVx_MODE
2004
	movf	PLUSW0, W
2005
	andlw	0x07
2006
	bz	SIDSE_L_ENV_SetPhase_NoLoop
2007
	addlw	-2
2008
	movwf	PRODL
2009
SIDSE_L_ENV_SetPhase_NoLoop
2010
 
2011
	;; if we are in sustain, and there is no loop point in the sustain phase, don't switch to next phase
2012
	movf	PRODH, W
2013
	xorlw	SID_ENV_STATE_SUSTAIN
2014
	bnz	SIDSE_L_ENV_SetPhase_NoSustain
2015
	movf	PRODL, W
2016
	xorlw	SID_ENV_STATE_SUSTAIN
2017
	bz	SIDSE_L_ENV_SetPhase_Sustain
2018
SIDSE_L_ENV_SetPhase_NoSustain
2019
	;; switch to next phase
2020
	incf	PRODL, F
2021
SIDSE_L_ENV_SetPhase_Sustain
2022
 
2023
	;; branch depending on new phase
2024
	BRA_IFSET PRODL, 2, ACCESS, SIDSE_L_ENV_SetPhase_4567
2025
SIDSE_L_ENV_SetPhase_0123
2026
	BRA_IFSET PRODL, 1, ACCESS, SIDSE_L_ENV_SetPhase_23
2027
SIDSE_L_ENV_SetPhase_01
2028
	movlw	0x01
2029
	btfsc	PRODL, 0
2030
	movlw 0x03
2031
	rgoto	SIDSE_L_ENV_SetPhase_Cont
2032
SIDSE_L_ENV_SetPhase_23
2033
	movlw	0x07
2034
	btfsc	PRODL, 0
2035
	movlw 0x0f
2036
	rgoto	SIDSE_L_ENV_SetPhase_Cont
2037
 
2038
SIDSE_L_ENV_SetPhase_4567
2039
	BRA_IFSET PRODL, 1, ACCESS, SIDSE_L_ENV_SetPhase_67
2040
SIDSE_L_ENV_SetPhase_45
2041
	movlw	0x1f
2042
	btfsc	PRODL, 0
2043
	movlw 0x3f
2044
	rgoto	SIDSE_L_ENV_SetPhase_Cont
2045
SIDSE_L_ENV_SetPhase_67
2046
	movlw	0x7f
2047
	;; 	rgoto	SIDSE_L_ENV_SetPhase_Cont
2048
SIDSE_L_ENV_SetPhase_Cont
2049
	movwf	PRODL
2050
	movlw	SID_ENVx_STATE
2051
	movff	PRODL, PLUSW1
2052
	return
2053
 
2054
;; --------------------------------------------------------------------------
2055
;;  FUNCTION: SIDSE_L_ENV_Restart
2056
;;  DESCRIPTION: help function which restarts a single ENV
2057
;;  IN: SID_PATCH_BUFFER_SHADOW + SID_Ix_ENV[123456]_BASE in FSR0
2058
;;      SID_ENV[123456]_BASE in FSR1
2059
;; --------------------------------------------------------------------------
2060
SIDSE_L_ENV_Restart
2061
	movlw	(1 << SID_ENV_STATE_ATTACK1)	; start at attack phase
2062
	movwf	PRODL
2063
	movlw	SID_ENVx_STATE
2064
	movff	PRODL, PLUSW1
2065
 
2066
	;; check if ENV should be delayed - set delay counter to 0x0001 in this case, else to 0x0000
2067
	movlw	SID_ENVx_DELAY_CTR_H	; high byte always reset to 0
2068
	clrf	PLUSW1
2069
 
2070
	movlw	SID_Ix_L_ENVx_DELAY
2071
	clrf	PRODL			; low byte set to 1 if delay != 0
2072
	movf	PLUSW0, W
2073
	skpz
2074
	incf	PRODL, F
2075
	movlw	SID_ENVx_DELAY_CTR_L
2076
	movff	PRODL, PLUSW1
2077
	return
2078
 
2079
;; --------------------------------------------------------------------------
2080
;;  FUNCTION: SIDSE_L_ENV_TrgRelease
2081
;;  DESCRIPTION: help function which starts release phase of a single ENV
2082
;;  IN: SID_ENV[123456]_BASE in FSR1
2083
;; --------------------------------------------------------------------------
2084
SIDSE_L_ENV_TrgRelease
2085
	movlw	SID_ENVx_STATE
2086
	bsf	PLUSW1, SID_ENV_STATE_RELEASE1
2087
	return
2088
 
2089
;; --------------------------------------------------------------------------
2090
;;  FUNCTION: SIDSE_L_Note_Restart
2091
;;  DESCRIPTION: help function which restarts the delay counter for voices
2092
;;               and requests an active gate
2093
;;  IN: patch base in FSR0, voice base in FSR1, osc number in SID_SE_ELEMENT_NUM
2094
;; --------------------------------------------------------------------------
2095
SIDSE_L_NOTE_Restart
2096
	;; request gate if voice is active (and request clear for proper ADSR handling)
2097
	;; set gate only if voice is active!
2098
	movlw	SID_Vx_STATE
2099
	bsf	PLUSW1, SID_V_STATE_GATE_CLR_REQ
2100
	btfsc	PLUSW1, SID_V_STATE_VOICE_ACTIVE
2101
	bsf	PLUSW1, SID_V_STATE_GATE_SET_REQ
2102
 
2103
	;; check if voice should be delayed - set delay counter to 0x0001 in this case, else to 0x0000
2104
	movlw	SID_Vx_SET_DELAY_CTR_H	; high byte always reset to 0
2105
	clrf	PLUSW1
2106
 
2107
	movlw	SID_Ix_Vx_DELAY
2108
	clrf	PRODL			; low byte set to 1 if delay != 0
2109
	movf	PLUSW0, W
2110
	skpz
2111
	incf	PRODL, F
2112
 
2113
	;; delay also if ABW (ADSR bug workaround) option active
2114
	movff	SID_PATCH_BUFFER_SHADOW + SID_Ix_OPT1_FLAGS, WREG
2115
	BRA_IFCLR WREG, SID_I_OPT1_FLAGS_ABW, ACCESS, SIDSE_L_NOTE_Restart_NoABW
2116
SIDSE_L_NOTE_Restart_ABW
2117
	movlw	0x01
2118
	movwf	PRODL
2119
 
2120
	;; clear ADSR registers, so that the envelope gets completely released
2121
	call	SIDSE_Hlp_GetSIDFrqPtr
2122
	movlw	SIDx_V1_ENV_AD
2123
	clrf	PLUSW2
2124
	movlw	SIDx_V1_ENV_SR
2125
	clrf	PLUSW2
2126
SIDSE_L_NOTE_Restart_NoABW
2127
 
2128
	movlw	SID_Vx_SET_DELAY_CTR_L
2129
	movff	PRODL, PLUSW1
2130
	return
2131
 
828 tk 2132
 
2133
 
2134
;; --------------------------------------------------------------------------
2135
;; This function updates the LED matrix
2136
;; For lead engine, this is interrupt driven for fastest update time
2137
;; only used when master is selected
2138
;; IN: -
2139
;; --------------------------------------------------------------------------
2140
SIDSE_L_CS_LM
2141
 
2142
	;; if slave is selected: exit (update done in CS_MENU_LED_Update_ModMatrix)
2143
	btfss	CS_MENU_SELECTED_SID_FLAGS, 0
2144
	return
2145
 
2146
	;; branch depending on normal/meter mode
2147
	BRA_IFSET CS_MENU_MODE, CS_MENU_MODE_MATRIX_METER_DISP, ACCESS, SIDSE_L_CS_LM_Meter
2148
SIDSE_L_CS_LM_Normal
2149
 
2150
	;; matrix is updated in CS_MENU_LED_Update_ModMatrix
2151
	;; no special code required here
2152
	return
2153
 
2154
SIDSE_L_CS_LM_Meter
2155
 
835 tk 2156
#if !DEFAULT_SAMMICHSID_CS
828 tk 2157
	;; meter values are updated in SIDSE_L_MOD_OP_Cont
2158
	;; no special code required here
2159
	return
2160
#else
2161
	;; use same function as for bassline engine
2162
	goto	SIDSE_L_CS_LM_Meter_ReUse
2163
#endif