Subversion Repositories svn.mios

Rev

Rev 897 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
44 tk 1
; $Id: sid_midi_b.inc 1122 2013-04-20 12:37:28Z tk $
1 tk 2
;
3
; MIDIbox SID
4
; MIDI Interface part for Bassline Engine
5
;
6
; ==========================================================================
7
;
8
;  Copyright 1998-2007 Thorsten Klose (tk@midibox.org)
9
;  Licensed for personal non-commercial use only.
10
;  All other rights reserved.
11
;
12
; ==========================================================================
13
 
14
 
15
;; --------------------------------------------------------------------------
16
;;  This function is called to forward a Note On event to the synthesizer
17
;;  Input:
18
;;     o MIDI Voice in SID_CURRENT_MIDI_VOICE
19
;;     o MIDI channel in SID_CURRENT_CHANNEL
20
;;     o note number in SID_MIDI_PARAMETER1
21
;;     o velocity in SID_MIDI_PARAMETER2
22
;; --------------------------------------------------------------------------
23
SID_MIDI_B_NoteOn
368 tk 24
	;; go through four midi voices
25
	;; 1 and 2 used to play the bassline/select the sequence
26
	;; 3 and 4 used to transpose a sequence
1 tk 27
	clrf	SID_CURRENT_MIDIVOICE, BANKED	; loop counter
28
	lfsr	FSR0, SID_MV1_BASE
29
SID_MIDI_B_NoteOn_Loop
30
 
31
	;; check if MIDI channel and split zone matches
32
	call	SID_MIDI_Hlp_ChkChnAndSplit
33
	bnz	SID_MIDI_B_NoteOn_Loop_Next
34
 
368 tk 35
	;; branch depending on voice
36
	BRA_IFCLR SID_CURRENT_MIDIVOICE, 1, BANKED, SID_MIDI_B_NoteOn_Loop_Voice
37
SID_MIDI_B_NoteOn_Loop_Trans
38
	;; determine pointer to note stack -> FSR2
39
	call	SID_MIDI_Hlp_GetNoteStackFSR2
40
	;; check the active note
41
	call	SID_MIDI_Hlp_CheckActiveNote
42
	bz	SID_MIDI_B_NoteOn_Loop_TransNClr
43
SID_MIDI_B_NoteOn_Loop_TransClr
44
	call	SID_MIDI_Hlp_ClrStack	; clear note stack (for the case that some notes are marked with bit #7 (key released)
45
SID_MIDI_B_NoteOn_Loop_TransNClr
46
	;; push note into stack
47
#if 0
48
	call	SID_MIDI_Hlp_PushArpHold ; push at the end of stack
49
#else
50
	call	SID_MIDI_Hlp_PushNote ; push at the beginning of stack
51
#endif
52
	rgoto	SID_MIDI_B_NoteOn_Loop_Next
53
 
54
SID_MIDI_B_NoteOn_Loop_Voice
1 tk 55
	;; set velocity value
56
	;; L/R selection depending on MIDI voice number
57
	movff	CS_MENU_SELECTED_SID_LR, TMP1		; taken from CS_MENU_SELECTED_SID_LR... dirty :-/
58
	movf	SID_CURRENT_MIDIVOICE, W, BANKED
59
	call	MIOS_HLP_GetBitORMask
60
	movwf	CS_MENU_SELECTED_SID_LR
61
	clrc
62
	rlf	SID_MIDI_PARAMETER2, W, BANKED
63
	movwf	MIOS_PARAMETER1
64
	movlw	SID_KNOB_VEL
65
	call	SID_KNOB_SetValue
66
	movff	TMP1, CS_MENU_SELECTED_SID_LR
67
 
68
	;; get pointer to instrument -> FSR2
69
	rcall	SID_MIDI_B_Hlp_FSR2_Ins
70
 
71
	;; SID_Ix_Vx_ARP_MODE of instrument -> TMP1
72
	movlw	SID_Ix_Vx_ARP_MODE
73
	movff	PLUSW2, TMP1
74
 
679 tk 75
	;; SID_Ix_Vx_ARP_SPEED_DIV of instrument -> TMP2
76
	movlw	SID_Ix_Vx_ARP_SPEED_DIV
77
	movff	PLUSW2, TMP2
78
 
1 tk 79
	;; copy SID_Ix_B_Vx_FLAGS2 to temporary register SID_MIDI_FLAGS
80
	movlw	SID_Ix_B_Vx_FLAGS2
81
	movff	PLUSW2, SID_MIDI_FLAGS
82
 
83
	;; calculate pointer to voice (SIDL/SIDR Voice 1)
84
	rcall	SID_MIDI_B_Hlp_FSR1_Voice
85
 
86
	;; branch depending on Normal/Arp/Sequencer mode
87
	BRA_IFSET SID_MIDI_FLAGS, SID_I_B_V_FLAGS2_WT_ONLY, BANKED, SID_MIDI_B_NoteOn_Loop_Seq
88
	BRA_IFSET TMP1, SID_I_V_ARP_MODE_ENABLE, ACCESS, SID_MIDI_B_NoteOn_Loop_Arp
89
SID_MIDI_B_NoteOn_Loop_Norm
90
	;; push note into WT stack
368 tk 91
	call	SID_MIDI_Hlp_GetNoteStackFSR2
1 tk 92
	lfsr	FSR2, SID_MV1_BASE + SID_MVx_WT_STACK_0
93
	movf	SID_CURRENT_MIDIVOICE, W, BANKED
94
	mullw	SID_MVx_RECORD_LEN
95
	movf	PRODL, W
96
	addwf	FSR2L, F
97
	call	SID_MIDI_Hlp_PushWT
98
 
99
	;; determine pointer to note stack -> FSR2
100
	movlw	SID_MVx_NOTE_STACK_0 - SID_MVx_WT_STACK_0
101
	addwf	FSR2L, F
102
 
103
	;; push note into stack
104
	rcall	SID_MIDI_Hlp_PushNote
105
 
106
	;; switch off gate if not in legato mode
107
	RCALL_IFCLR SID_MIDI_FLAGS, SID_I_B_V_FLAGS2_LEGATO, BANKED, SID_MIDI_B_Hlp_GateOff
108
 
109
	;; call note-on handler
110
	rcall	SID_MIDI_B_Hlp_NoteOn
111
	rgoto	SID_MIDI_B_NoteOn_Loop_Next
112
 
113
SID_MIDI_B_NoteOn_Loop_Arp
114
	;; save voice number in midivoice (instrument) record
115
	movlw	SID_MVx_LAST_VOICE
116
	movff	SID_CURRENT_VOICE, PLUSW0
117
	;; save midivoice (instrument) number in voice record
118
	movlw	SID_Vx_ASSIGNED_MV
119
	movff	SID_CURRENT_MIDIVOICE, PLUSW1
120
	;; determine pointer to note stack -> FSR2
368 tk 121
	call	SID_MIDI_Hlp_GetNoteStackFSR2
1 tk 122
	;; call Arp handler
123
	call	SID_MIDI_Hlp_ArpNoteOn
124
	rgoto	SID_MIDI_B_NoteOn_Loop_Next
125
 
126
 
127
SID_MIDI_B_NoteOn_Loop_Seq
128
	;; push note into WT stack
129
	lfsr	FSR2, SID_MV1_BASE + SID_MVx_WT_STACK_0
130
	movf	SID_CURRENT_MIDIVOICE, W, BANKED
131
	mullw	SID_MVx_RECORD_LEN
132
	movf	PRODL, W
133
	addwf	FSR2L, F
134
	call	SID_MIDI_Hlp_PushWT
135
 
136
	;; determine pointer to note stack -> FSR2
137
	movlw	SID_MVx_NOTE_STACK_0 - SID_MVx_WT_STACK_0
138
	addwf	FSR2L, F
139
 
140
	;; push note into stack
141
	rcall	SID_MIDI_Hlp_PushNote
142
 
368 tk 143
	;; save midivoice (instrument) number in voice record
144
	movlw	SID_Vx_ASSIGNED_MV
145
	movff	SID_CURRENT_MIDIVOICE, PLUSW1
146
 
1 tk 147
	;; reset sequencer if voice was not active before
148
	;; do this with both voices for proper synchronisation!
149
 
881 tk 150
	;; only done in master mode
1 tk 151
	BRA_IFSET SID_STAT, SID_STAT_CLK_SLAVE, ACCESS, SID_MIDI_B_NoteOn_Loop_Seq_NoR01
152
 
153
	movff	SIDL_V1_BASE + SID_Vx_STATE, WREG
154
	BRA_IFSET WREG, SID_V_STATE_VOICE_ACTIVE, ACCESS, SID_MIDI_B_NoteOn_Loop_Seq_NoR0
155
SID_MIDI_B_NoteOn_Loop_Seq_R0
156
	movlw	0x01
157
	iorwf	SID_SE_TRG_EVNT_U, F, BANKED
158
SID_MIDI_B_NoteOn_Loop_Seq_NoR0
159
 
160
	movff	SIDR_V1_BASE + SID_Vx_STATE, WREG
161
	BRA_IFSET WREG, SID_V_STATE_VOICE_ACTIVE, ACCESS, SID_MIDI_B_NoteOn_Loop_Seq_NoR1
162
SID_MIDI_B_NoteOn_Loop_Seq_R1
163
	movlw	0x02
164
	iorwf	SID_SE_TRG_EVNT_U, F, BANKED
165
SID_MIDI_B_NoteOn_Loop_Seq_NoR1
166
SID_MIDI_B_NoteOn_Loop_Seq_NoR01
167
 
168
	;; select new sequence
169
	rcall	SID_MIDI_B_Hlp_SetSeq
170
 
171
	;; always set voice active flag of both voices to ensure that they are in sync
897 tk 172
	;; ensure that this is only done for instruments where WTO (sequencer enabled) is selected
1 tk 173
	SET_BSR	SIDL_V1_BASE
174
	movff	SID_PATCH_BUFFER_SHADOW + SID_Ix_B_S1V1_BASE + SID_Ix_B_Vx_FLAGS2, WREG
175
	btfsc	WREG, SID_I_B_V_FLAGS2_WT_ONLY
176
	bsf	SIDL_V1_BASE + SID_Vx_STATE, SID_V_STATE_VOICE_ACTIVE
177
 
178
	movff	SID_PATCH_BUFFER_SHADOW + SID_Ix_B_S2V1_BASE + SID_Ix_B_Vx_FLAGS2, WREG
179
	btfsc	WREG, SID_I_B_V_FLAGS2_WT_ONLY
180
	bsf	SIDR_V1_BASE + SID_Vx_STATE, SID_V_STATE_VOICE_ACTIVE
181
	SET_BSR	SID_BASE
182
	;; 	rgoto	SID_MIDI_B_NoteOn_Loop_Next
183
 
184
 
185
SID_MIDI_B_NoteOn_Loop_Next
186
	movlw	SID_MVx_RECORD_LEN
187
	addwf	FSR0L, F
188
	incf	SID_CURRENT_MIDIVOICE, F, BANKED
368 tk 189
	movlw	4 - 1
1 tk 190
	cpfsgt	SID_CURRENT_MIDIVOICE, BANKED
191
	rgoto SID_MIDI_B_NoteOn_Loop
192
 
193
SID_MIDI_B_NoteOn_End
194
	return
195
 
196
 
197
;; --------------------------------------------------------------------------
198
;;  This function is called to forward a Note Off event to the synthesizer
199
;;  Input:
200
;;     o MIDI channel in SID_CURRENT_CHANNEL
201
;;     o note number in SID_MIDI_PARAMETER1
202
;;     o velocity in SID_MIDI_PARAMETER2
203
;; --------------------------------------------------------------------------
204
SID_MIDI_B_NoteOff
205
	SET_BSR	SID_BASE
206
 
368 tk 207
	;; go through four midi voices
208
	;; 1 and 2 used to play the bassline/select the sequence
209
	;; 3 and 4 used to transpose a sequence
1 tk 210
	clrf	SID_CURRENT_MIDIVOICE, BANKED		; loop counter
211
	clrf	SID_CURRENT_VOICE, BANKED	; corresponding voice number (0 or 3)
212
	lfsr	FSR0, SID_MV1_BASE
213
SID_MIDI_B_NoteOff_Loop
214
 
215
	;; check if MIDI channel and split zone matches
216
	call	SID_MIDI_Hlp_ChkChnAndSplit
217
	bnz	SID_MIDI_B_NoteOff_Loop_Next
218
 
368 tk 219
	;; branch depending on voice
220
	BRA_IFCLR SID_CURRENT_MIDIVOICE, 1, BANKED, SID_MIDI_B_NoteOff_Loop_Voice
221
SID_MIDI_B_NoteOff_Loop_Trans
222
	;; determine pointer to note stack -> FSR2
223
	call	SID_MIDI_Hlp_GetNoteStackFSR2
224
	;; pop note from stack
225
	call	SID_MIDI_Hlp_PopArpHold
226
	;; TODO: add new algorithm which shifts the de-activated note to the end of the stack
227
	;; this would allow following handling (example):
228
	;; Press C-3: plays sequence with base note
229
	;; Press E-3 in addition: transposes sequence by +4
230
	;; Depress E-3: currently holds the transpose - desired behaviour: play C-3 (base note) again, since the key is still pressed
231
	rgoto	SID_MIDI_B_NoteOff_Loop_Next
232
 
233
SID_MIDI_B_NoteOff_Loop_Voice
1 tk 234
	;; SID_Ix_Vx_ARP_MODE of instrument -> TMP1
235
	rcall	SID_MIDI_B_Hlp_FSR2_Ins
236
	movlw	SID_Ix_Vx_ARP_MODE
237
	movff	PLUSW2, TMP1
238
 
679 tk 239
	;; SID_Ix_Vx_ARP_SPEED_DIV of instrument -> TMP2
240
	movlw	SID_Ix_Vx_ARP_SPEED_DIV
241
	movff	PLUSW2, TMP2
242
 
1 tk 243
	;; copy SID_Ix_B_Vx_FLAGS2 to temporary register SID_MIDI_FLAGS
244
	movlw	SID_Ix_B_Vx_FLAGS2
245
	movff	PLUSW2, SID_MIDI_FLAGS
246
 
247
	;; pop note from WT stack
248
	lfsr	FSR2, SID_MV1_BASE + SID_MVx_WT_STACK_0
249
	movf	SID_CURRENT_MIDIVOICE, W, BANKED
250
	mullw	SID_MVx_RECORD_LEN
251
	movf	PRODL, W
252
	addwf	FSR2L, F
253
	call	SID_MIDI_Hlp_PopWT
254
 
255
	;; calculate pointer to voice (SIDL/SIDR Voice 1)
256
	rcall	SID_MIDI_B_Hlp_FSR1_Voice
257
 
258
	;; determine pointer to note stack -> FSR2
259
	movlw	SID_MVx_NOTE_STACK_0 - SID_MVx_WT_STACK_0
260
	addwf	FSR2L, F
261
	movff	INDF2, TMP3	; save current #0 entry in TMP3 for later use
262
 
263
	;; branch depending on Normal/Arp/Sequencer mode
264
	BRA_IFSET SID_MIDI_FLAGS, SID_I_B_V_FLAGS2_WT_ONLY, BANKED, SID_MIDI_B_NoteOff_Loop_Seq
265
	BRA_IFSET TMP1, SID_I_V_ARP_MODE_ENABLE, ACCESS, SID_MIDI_B_NoteOff_Loop_Arp
266
SID_MIDI_B_NoteOff_Loop_Norm
267
	;; pop note from stack (pointer to stack in FSR2)
268
	rcall	SID_MIDI_Hlp_PopNote
843 tk 269
	bnz	SID_MIDI_B_NoteOff_Loop_Next ; ZERO flag cleared: note not found!
1 tk 270
 
271
	movf	TMP3, W		; restore note
272
	rcall	SID_MIDI_B_Hlp_NoteOff
273
	RCALL_IFSET WREG, 0, ACCESS, SID_MIDI_B_Hlp_NoteOn
274
	rgoto	SID_MIDI_B_NoteOff_Loop_Next
275
 
276
 
277
SID_MIDI_B_NoteOff_Loop_Arp
278
	;; call Arp handler
279
	call	SID_MIDI_Hlp_ArpNoteOff
280
	rgoto	SID_MIDI_B_NoteOff_Loop_Next
281
 
282
 
283
SID_MIDI_B_NoteOff_Loop_Seq
284
	;; pop note from stack (pointer to stack in FSR2)
285
	rcall	SID_MIDI_Hlp_PopNote
843 tk 286
	bnz	SID_MIDI_B_NoteOff_Loop_Next ; ZERO flag cleared: note not found!
1 tk 287
 
288
	;; FSR2 -> pointer to instrument patch
289
	rcall	SID_MIDI_B_Hlp_FSR2_Ins
290
 
291
	;; select sequence if there is still a note in stack
292
	movlw	SID_MVx_NOTE_STACK_PTR
293
	movf	PLUSW0, W
294
	skpz
295
	rcall	SID_MIDI_B_Hlp_SetSeq
296
 
297
;; disabled --- hold mode always activated, sequence can be disabled with key G#/A/A#/B
298
#if 0
299
	;; clear "voice active" flag if no note played and no sequence active
300
	rcall	SID_MIDI_B_Hlp_FSR2_Ins
301
	movlw	SID_Ix_B_Vx_SEQ_SPEED
302
	BRA_IFSET PLUSW2, SID_I_V_SEQ_HOLD, ACCESS, SID_MIDI_B_NoteOff_Loop_Seq_NoS
303
	movlw	SID_MVx_NOTE_STACK_PTR
304
	movf	PLUSW0, W
305
	bnz	SID_MIDI_B_NoteOff_Loop_Seq_NoS
306
SID_MIDI_B_NoteOff_Loop_Seq_S
307
	movlw	SID_Vx_STATE
308
	bcf	PLUSW1, SID_V_STATE_VOICE_ACTIVE
309
SID_MIDI_B_NoteOff_Loop_Seq_NoS
310
#endif
311
 
312
	;; disable voice active flag of both voices if both are playing invalid sequences (seq off)
313
	;; only used in master mode
314
	BRA_IFSET SID_STAT, SID_STAT_CLK_SLAVE, ACCESS, SID_MIDI_B_NoteOff_Loop_Seq_NoDs
315
 
316
	;; always set voice active flag of both voices to ensure that they are in sync
317
	movff	SID_PATCH_BUFFER_SHADOW + SID_Ix_B_S1V1_BASE + SID_Ix_B_Vx_SEQ_NUM, WREG
318
	andlw	0xf8
319
	bz	SID_MIDI_B_NoteOff_Loop_Seq_NoDs
320
	movff	SID_PATCH_BUFFER_SHADOW + SID_Ix_B_S2V1_BASE + SID_Ix_B_Vx_SEQ_NUM, WREG
321
	andlw	0xf8
322
	bz	SID_MIDI_B_NoteOff_Loop_Seq_NoDs
323
SID_MIDI_B_NoteOff_Loop_Seq_Dis
324
	;; ensure that this is only done for instruments where WTO (sequence) is selected
325
	SET_BSR	SIDL_V1_BASE
326
	movff	SID_PATCH_BUFFER_SHADOW + SID_Ix_B_S1V1_BASE + SID_Ix_B_Vx_FLAGS2, WREG
327
	btfsc	WREG, SID_I_B_V_FLAGS2_WT_ONLY
328
	bcf	SIDL_V1_BASE + SID_Vx_STATE, SID_V_STATE_VOICE_ACTIVE, BANKED
329
 
330
	movff	SID_PATCH_BUFFER_SHADOW + SID_Ix_B_S2V1_BASE + SID_Ix_B_Vx_FLAGS2, WREG
331
	btfsc	WREG, SID_I_B_V_FLAGS2_WT_ONLY
332
	bcf	SIDR_V1_BASE + SID_Vx_STATE, SID_V_STATE_VOICE_ACTIVE, BANKED
333
	SET_BSR	SID_BASE
334
SID_MIDI_B_NoteOff_Loop_Seq_NoDs
335
 
336
	;; 	rgoto	SID_MIDI_B_NoteOff_Loop_Next
337
 
338
 
339
SID_MIDI_B_NoteOff_Loop_Next
340
	movlw	SID_MVx_RECORD_LEN
341
	addwf	FSR0L, F
342
	incf	SID_CURRENT_MIDIVOICE, F, BANKED
368 tk 343
	movlw	4 - 1
1 tk 344
	cpfsgt	SID_CURRENT_MIDIVOICE, BANKED
345
	rgoto SID_MIDI_B_NoteOff_Loop
346
 
347
SID_MIDI_B_NoteOff_End
348
	return
349
 
350
 
351
;; --------------------------------------------------------------------------
352
;;  This function is called to forward a PitchBender event to the synthesizer
353
;;  Input:
354
;;     o MIDI channel in SID_CURRENT_CHANNEL
355
;;     o 8bit PitchBender value in SID_MIDI_PARAMETER1
356
;; --------------------------------------------------------------------------
357
SID_MIDI_B_PitchBender
358
	;; first MIDI voice has already been handled in sid_midi.inc
359
	;; now check for MIDI channel of second voice
360
 
361
	;; forward to knob handler (only checks for MIDI channel of first MIDI voice)
362
	lfsr	FSR0, SID_MV2_BASE
363
 
364
	;; check for MIDI channel
365
	movlw	SID_MVx_MIDI_CHANNEL
366
	movf	PLUSW0, W
367
	cpfseq	SID_CURRENT_CHANNEL, BANKED
368
	rgoto SID_MIDI_B_PitchBender_NoKnob
369
SID_MIDI_B_PitchBender_Knob
370
	;; select second instrument
371
	movff	CS_MENU_SELECTED_SID_LR, TMP1		; taken from CS_MENU_SELECTED_SID_LR... dirty :-/
372
	movlw	0x02
373
	movwf	CS_MENU_SELECTED_SID_LR
374
 
375
	;; copy converted pitch bender into mod matrix source
376
	movff	SID_MIDI_PARAMETER1, MIOS_PARAMETER1
377
	movlw	SID_KNOB_PB
378
	call	SID_KNOB_SetValue
379
	movff	TMP1, CS_MENU_SELECTED_SID_LR
380
SID_MIDI_B_PitchBender_NoKnob
381
	return
382
 
383
 
384
;; --------------------------------------------------------------------------
385
;;  This function is called to forward a CC event to the synthesizer
386
;;  Input:
387
;;     o MIDI channel in SID_CURRENT_CHANNEL
388
;;     o CC number in SID_MIDI_PARAMETER1
389
;;     o CC value in SID_MIDI_PARAMETER2
390
;; --------------------------------------------------------------------------
391
SID_MIDI_B_CC
392
	SET_BSR	SID_BASE
393
 
394
	;; go through all midi voices
395
	clrf	SID_CURRENT_MIDIVOICE, BANKED	; loop counter
396
	lfsr	FSR0, SID_MV1_BASE
397
SID_MIDI_B_CC_Loop
398
	;; check for MIDI channel
399
	movlw	SID_MVx_MIDI_CHANNEL
400
	movf	PLUSW0, W
401
	cpfseq	SID_CURRENT_CHANNEL, BANKED
402
	rgoto SID_MIDI_B_CC_Loop_Next
403
 
1122 tk 404
	;; if CC#06 (NRPN data MSB) received, forward to parameter handler
1 tk 405
	movlw	0x06
406
	cpfseq	SID_MIDI_PARAMETER1, BANKED
407
	rgoto SID_MIDI_B_CC_NoNRPNDataH
408
SID_MIDI_B_CC_NRPNDataH
409
	;; prepare MIOS_PARAMETER3 (selection options)
410
	swapf	SID_CURRENT_MIDIVOICE, W, BANKED	; expecting instrument in MIOS_PARAMETER3[6:4]
411
	movwf	MIOS_PARAMETER3		; (L/R selection done in NRPN function)
412
	call	SID_PARIN_SetNRPN
413
	rgoto	SID_MIDI_B_CC_Loop_Next
414
SID_MIDI_B_CC_NoNRPNDataH
415
 
416
	;; if CC#64 (Sustain) received, set/clear sustain flags and release notes if required
417
	movlw	0x40
418
	cpfseq	SID_MIDI_PARAMETER1, BANKED
419
	rgoto SID_MIDI_B_CC_Not64
420
SID_MIDI_B_CC_64
421
	;; TODO: not supported yet
422
SID_MIDI_B_CC_Not64
423
 
1122 tk 424
	;; handle remaining CCs
425
	movf	SID_CURRENT_MIDIVOICE, W, BANKED	; expecting instrument in MIOS_PARAMETER3[5:4]
426
	call	MIOS_HLP_GetBitORMask
427
	andlw	0x03
428
	swapf	WREG, W
429
	movwf	MIOS_PARAMETER3
430
	call	SID_CC_TABLE_Set
431
 
1 tk 432
SID_MIDI_B_CC_Loop_Next
433
 
434
	movlw	SID_MVx_RECORD_LEN
435
	addwf	FSR0L, F
436
	incf	SID_CURRENT_MIDIVOICE, F, BANKED
437
	movlw	2-1
438
	cpfsgt	SID_CURRENT_MIDIVOICE, BANKED
439
	rgoto SID_MIDI_B_CC_Loop
440
 
441
SID_MIDI_B_CC_Loop_End
442
	return
443
 
444
 
445
;; --------------------------------------------------------------------------
446
;;  help routines for Bassline Engine
447
;; --------------------------------------------------------------------------
448
 
449
;; --------------------------------------------------------------------------
450
;; Note On help function
451
;; IN: pointer to voice in FSR1, pointer to MIDI voice in FSR0
452
;;     MIDI voice number in SID_CURRENT_MIDIVOICE
453
;;     Voice number in SID_CURRENT_VOICE
454
;; ALSO USED BY SID_PATCH_Init !
455
;; --------------------------------------------------------------------------
456
SID_MIDI_B_Hlp_NoteOn
457
	;; save note into SID_Vx_NOTE and SID_Vx_PLAYED_NOTE (last one is relevant for MIDI handler)
458
	movlw	SID_MVx_NOTE_STACK_0
459
	movff	PLUSW0, PRODL
460
	movlw	SID_Vx_NOTE
461
	movff	PRODL, PLUSW1
462
	movlw	SID_Vx_PLAYED_NOTE
463
	movff	PRODL, PLUSW1
464
 
465
	;; sus-key activated?
466
	BRA_IFCLR SID_MIDI_FLAGS, SID_I_B_V_FLAGS2_SUS_KEY, BANKED, SID_MIDI_B_Hlp_NoteOn_NoSusKey
467
SID_MIDI_B_Hlp_NoteOn_SusKey
228 tk 468
	;; in suy-key mode, we activate portamento only if at least one key is played
469
	movlw	SID_MVx_NOTE_STACK_PTR
470
	decf	PLUSW0, W
471
	bz	SID_MIDI_B_Hlp_NoteOn_NoSusKeyPr
1 tk 472
SID_MIDI_B_Hlp_NoteOn_NoSusKey
399 tk 473
	;; omit portamento if first key played after patch initialisation
474
	movlw	SID_Vx_STATE2
475
	BRA_IFCLR PLUSW1, SID_V_STATE2_PORTA_INITIALIZED, ACCESS, SID_MIDI_B_Hlp_NoteOn_NoSusKeyPr
1 tk 476
	movlw	SID_Vx_STATE
477
	bsf	PLUSW1, SID_V_STATE_PORTA_ACTIVE
478
SID_MIDI_B_Hlp_NoteOn_NoSusKeyPr
479
 
399 tk 480
	;; next key will allow portamento
481
	movlw	SID_Vx_STATE2
482
	bsf	PLUSW1, SID_V_STATE2_PORTA_INITIALIZED
483
 
1 tk 484
	;; skip the rest if legato and voice already active
485
	BRA_IFCLR SID_MIDI_FLAGS, SID_I_B_V_FLAGS2_LEGATO, BANKED, SID_MIDI_B_Hlp_NoteOn_NoLegato
486
SID_MIDI_B_Hlp_NoteOn_Legato
487
	movlw	SID_Vx_STATE
488
	BRA_IFSET PLUSW1, SID_V_STATE_VOICE_ACTIVE, ACCESS, SID_MIDI_B_Hlp_NoteOn_NoGate
489
SID_MIDI_B_Hlp_NoteOn_NoLegato
490
 
491
	;; request gate bit
492
	rcall	SID_MIDI_B_Hlp_GateOn
493
 
494
SID_MIDI_B_Hlp_NoteOn_NoGate
495
 
496
	;; don't sync if WTO mode or legato mode and current note is first note
497
	RCALL_IFCLR SID_MIDI_FLAGS, SID_I_B_V_FLAGS2_LEGATO, BANKED, SID_MIDI_B_Hlp_NoteOn_NOnTrg
498
	movlw	SID_MVx_NOTE_STACK_0
499
	movff	PLUSW0, PRODL
500
	movf	SID_MIDI_PARAMETER1, W, BANKED
501
	cpfseq	PRODL, ACCESS
502
	rgoto SID_MIDI_B_Hlp_NoteOn_NoNOnTrg
503
	movlw	SID_MVx_NOTE_STACK_1
504
	movf	PLUSW0, W
505
	bnz	SID_MIDI_B_Hlp_NoteOn_NoNOnTrg
506
SID_MIDI_B_Hlp_NoteOn_NOnTrg
880 tk 507
	;; TODO: ??? removed code???
1 tk 508
SID_MIDI_B_Hlp_NoteOn_NoNOnTrg
509
 
510
	;; save voice number in midivoice (instrument) record
511
	movlw	SID_MVx_LAST_VOICE
512
	movff	SID_CURRENT_VOICE, PLUSW0
513
 
514
	;; save midivoice (instrument) number in voice record
515
	movlw	SID_Vx_ASSIGNED_MV
516
	movff	SID_CURRENT_MIDIVOICE, PLUSW1
517
 
518
	return
519
 
520
;; --------------------------------------------------------------------------
521
;; Note Off help function
522
;; IN: pointer to voice in FSR1, pointer to MIDI voice in FSR0
523
;; OUT: returns 0x01 if gate should be retriggered (mono mode, more than one note was played)
524
;; --------------------------------------------------------------------------
525
SID_MIDI_B_Hlp_NoteOff
526
	;; last note number of #0 (before pop) in WREG!
527
	movwf	TABLAT
528
 
529
	;; if not in legato mode and current note-off number equal to last entry #0: gate off
530
	movf	TABLAT, W
531
	cpfseq	SID_MIDI_PARAMETER1, BANKED
532
	rgoto SID_MIDI_B_Hlp_NoteOff_End
533
	BRA_IFSET SID_MIDI_FLAGS, SID_I_B_V_FLAGS2_LEGATO, BANKED, SID_MIDI_B_Hlp_NoteOff_NoGOff
534
	rcall	SID_MIDI_B_Hlp_GateOff
535
SID_MIDI_B_Hlp_NoteOff_NoGOff
536
	;; ------------------------------------------------------------------
537
 
538
	;; if there is still a note in the stack, play new note with NoteOn function (checked by caller)
539
	movlw	SID_MVx_NOTE_STACK_PTR
540
	movf	PLUSW0, W
842 tk 541
	bz	SID_MIDI_B_Hlp_NoteOff_GOff
542
 
543
	;; activate portamento (will be ignored by Pitch handler if no portamento active - important for SusKey function to have it here!)
544
	movlw	SID_Vx_STATE
545
	bsf	PLUSW1, SID_V_STATE_PORTA_ACTIVE
546
 
1 tk 547
	retlw	0x01		; return, request Note On!
548
 
549
SID_MIDI_B_Hlp_NoteOff_GOff
550
	;; else request gate clear bit
551
	rcall	SID_MIDI_B_Hlp_GateOff
552
 
553
SID_MIDI_B_Hlp_NoteOff_End
554
	retlw	0x00		; return, request NO Note On!
555
 
556
 
557
;; --------------------------------------------------------------------------
558
;; Gate On help function
559
;; IN: pointer to voice in FSR1, pointer to MIDI voice in FSR0
560
;;     voice number in SID_CURRENT_VOICE
561
;; --------------------------------------------------------------------------
562
SID_MIDI_B_Hlp_GateOn
563
	;; set "voice active" flag
564
	movlw	SID_Vx_STATE
565
	bsf	PLUSW1, SID_V_STATE_VOICE_ACTIVE
566
 
880 tk 567
	;; request gate via trigger matrix
1 tk 568
	movf	SID_CURRENT_VOICE, W, BANKED
569
	call	MIOS_HLP_GetBitORMask
570
	iorwf	SID_SE_TRG_EVNT_L, F, BANKED
571
 
572
	;; request LFO re-sync
573
	movf	SID_CURRENT_VOICE, W, BANKED
574
	addlw	2
575
	call	MIOS_HLP_GetBitORMask
576
	iorwf	SID_SE_TRG_EVNT_H, F, BANKED
577
	movf	SID_CURRENT_VOICE, W, BANKED
578
	movlw	0x01
579
	skpz
580
	movlw	0x02
581
	iorwf	SID_SE_TRG_EVNT_U, F, BANKED
582
 
583
	;; ENV attack phase via trigger matrix
584
	movf	SID_CURRENT_VOICE, W, BANKED
585
	call	MIOS_HLP_GetBitORMask
586
	iorwf	SID_SE_TRG_EVNT_ENVA, F, BANKED
587
 
588
	;; set accent flag depending on velocity (set when velocity >= 0x40)
589
	movlw	SID_Vx_STATE
590
	bcf	PLUSW1, SID_V_STATE_ACCENT
591
	btfsc	SID_MIDI_PARAMETER2, 6, BANKED
592
	bsf	PLUSW1, SID_V_STATE_ACCENT
593
 
594
SID_MIDI_B_Hlp_GateOn_End
595
	return
596
 
597
;; --------------------------------------------------------------------------
598
;; Gate Off help function
599
;; IN: pointer to voice in FSR1, pointer to MIDI voice in FSR0
600
;;     note in SID_MIDI_PARAMETER1, velocity in SID_MIDI_PARAMETER2
601
;; --------------------------------------------------------------------------
602
SID_MIDI_B_Hlp_GateOff
603
	movlw	SID_Vx_STATE
604
	BRA_IFCLR PLUSW1, SID_V_STATE_VOICE_ACTIVE, ACCESS, SID_MIDI_B_Hlp_GateOff_End
605
 
606
	movlw	SID_Vx_PLAYED_NOTE
607
	movf	PLUSW1, W
608
	cpfseq	SID_MIDI_PARAMETER1, BANKED
609
	rgoto SID_MIDI_B_Hlp_GateOff_End
610
 
880 tk 611
	;; request gate off
1 tk 612
	movlw	SID_Vx_STATE
613
	bcf	PLUSW1, SID_V_STATE_VOICE_ACTIVE
614
	bcf	PLUSW1, SID_V_STATE_GATE_SET_REQ
615
 
880 tk 616
	;; request gate clear
1 tk 617
	movf	SID_CURRENT_VOICE, W, BANKED
618
	call	MIOS_HLP_GetBitORMask
619
	movlw	SID_Vx_STATE
620
	bsf	PLUSW1, SID_V_STATE_GATE_CLR_REQ
621
 
622
	;; ENV release phase via trigger matrix
623
	movf	SID_CURRENT_VOICE, W, BANKED
624
	call	MIOS_HLP_GetBitORMask
625
	iorwf	SID_SE_TRG_EVNT_ENVR, F, BANKED
626
 
627
SID_MIDI_B_Hlp_GateOff_End
628
	return
629
 
630
 
631
;; --------------------------------------------------------------------------
632
;; Help function which returns a pointer to the SID voice of a MIDI voice in FSR1
633
;; IN: SID_CURRENT_MIDIVOICE
634
;; OUT: pointer to voice in FSR1, voice number in SID_CURRENT_VOICE
635
;; --------------------------------------------------------------------------
636
SID_MIDI_B_Hlp_FSR1_Voice
637
	;; MIDI instrument 0 -> SIDL_V1_VOICE (voice #0)
638
	;; MIDI instrument 1 -> SIDR_V1_VOICE (voice #3)
639
 
640
	movf	SID_CURRENT_MIDIVOICE, W, BANKED
641
	skpz
642
	movlw	3
643
	movwf	SID_CURRENT_VOICE, BANKED
644
 
645
	lfsr	FSR1, SIDL_V1_BASE
646
	skpz
647
	lfsr	FSR1, SIDR_V1_BASE
648
	return
649
 
650
 
651
;; --------------------------------------------------------------------------
652
;; Help function which returns a pointer to the assigned instrument
653
;; of a MIDI voice in FSR2
654
;; IN: SID_CURRENT_MIDIVOICE
655
;; OUT: pointer to instrument in FSR2
656
;; --------------------------------------------------------------------------
657
SID_MIDI_B_Hlp_FSR2_Ins
658
	lfsr	FSR2, SID_PATCH_BUFFER_SHADOW + SID_Ix_B_S1V1_BASE
659
	movf	SID_CURRENT_MIDIVOICE, W, BANKED
660
	mullw	SID_Ix_B_S2V1_BASE-SID_Ix_B_S1V1_BASE
661
	movf	PRODL, W
662
	addwf	FSR2L, F
663
	movf	PRODH, W
664
	addwfc	FSR2H, F
665
	return
666
 
667
 
668
;; --------------------------------------------------------------------------
669
;; Help function which selects the sequence based on played note
670
;; IN: SID_CURRENT_MIDIVOICE (0 or 1), voice base in FSR1, midi voice base in FSR0
671
;; --------------------------------------------------------------------------
672
SID_MIDI_B_Hlp_SetSeq
673
	;; get first note
674
	movlw	SID_MVx_NOTE_STACK_0
675
	movff	PLUSW0, PRODL
676
 
677
	;; add MIDI voice based transpose value (ensure that within range 0x00..0x7f)
678
	movlw	SID_MVx_TRANSPOSE
679
	movf	PLUSW0, W
680
	addlw	-0x40
681
	BRA_IFSET WREG, 7, ACCESS, SID_MIDI_B_Hlp_SetSeq_TrnN
682
SID_MIDI_B_Hlp_SetSeq_TrnP
683
	addwf	PRODL, F
684
	BRA_IFCLR PRODL, 7, ACCESS, SID_MIDI_B_Hlp_SetSeq_Trn_Cont
685
	addlw	-12
686
	rgoto	SID_MIDI_B_Hlp_SetSeq_TrnP
687
SID_MIDI_B_Hlp_SetSeq_TrnN
688
	addwf	PRODL, F
689
	BRA_IFCLR PRODL, 7, ACCESS, SID_MIDI_B_Hlp_SetSeq_Trn_Cont
690
	movlw	12
691
	rgoto	SID_MIDI_B_Hlp_SetSeq_TrnN
692
SID_MIDI_B_Hlp_SetSeq_Trn_Cont
693
 
694
	;; store note in voice record
695
	movlw	SID_Vx_PLAYED_NOTE
696
	movff	PRODL, PLUSW1
697
 
698
 
699
	;; determine sequence based on note number
700
	;; remove octave from note
701
SID_MIDI_B_Hlp_SetSeq_RemoveOct
702
	movlw	12 - 1
703
	cpfsgt	PRODL, ACCESS
704
	rgoto SID_MIDI_B_Hlp_SetSeq_OctOk
705
	movlw	-12
706
	addwf	PRODL, F
707
	rgoto	SID_MIDI_B_Hlp_SetSeq_RemoveOct
708
 
709
SID_MIDI_B_Hlp_SetSeq_OctOk
710
 
711
	;; if note number >= 8: set to 8 (sequence off)
712
	movlw	8
713
	cpfslt	PRODL, ACCESS
714
	movwf PRODL
715
 
716
	;; set new sequence
717
	BRA_IFSET SID_CURRENT_MIDIVOICE, 0, BANKED, SID_MIDI_B_Hlp_SetSeq_1
718
SID_MIDI_B_Hlp_SetSeq_0
719
	;; patch/shadow buffer
720
	movff	PRODL, SID_PATCH_BUFFER + SID_Ix_B_S1V1_BASE + SID_Ix_B_Vx_SEQ_NUM
721
	movff	PRODL, SID_PATCH_BUFFER_SHADOW + SID_Ix_B_S1V1_BASE + SID_Ix_B_Vx_SEQ_NUM
722
 
723
	;; forward to edit buffer if SID selected
724
	call	CS_MENU_MS_GetSIDNumber
725
	xorwf	CS_MENU_EDIT_BUFFER_SID, W
726
	skpnz
727
	movff	PRODL, SID_EDIT_BUFFER + SID_Ix_B_S1V1_BASE + SID_Ix_B_Vx_SEQ_NUM
728
 
729
	return
730
 
731
SID_MIDI_B_Hlp_SetSeq_1
732
	;; patch/shadow buffer
733
	movff	PRODL, SID_PATCH_BUFFER + SID_Ix_B_S2V1_BASE + SID_Ix_B_Vx_SEQ_NUM
734
	movff	PRODL, SID_PATCH_BUFFER_SHADOW + SID_Ix_B_S2V1_BASE + SID_Ix_B_Vx_SEQ_NUM
735
 
736
	;; forward to edit buffer if SID selected
737
	call	CS_MENU_MS_GetSIDNumber
738
	xorwf	CS_MENU_EDIT_BUFFER_SID, W
739
	skpnz
740
	movff	PRODL, SID_EDIT_BUFFER + SID_Ix_B_S2V1_BASE + SID_Ix_B_Vx_SEQ_NUM
741
 
742
	return
743