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 |