Subversion Repositories svn.mios

Rev

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

Rev Author Line No. Line
44 tk 1
; $Id: sidplay.inc 44 2008-01-30 21:39:30Z tk $
1 tk 2
;
3
; SIDplayer - SysEx Parser
4
;
5
; This MIOS applications interprets the SIDstation "ASID" protocol and
6
; forwards the requested register changes to a MBHP_SID module
7
;
8
; compatible with the ASID player and SIDPLAY/Windows
9
; -> http://www.d.kth.se/~d93-alo/c64/spw/sidplayw.html
10
; -> http://www.sidstation.com/sidsupport.php
11
; -> http://www.sidstation.com/files/asid_xp_1.0.zip
12
;
13
; based on http://sammal.ton.tut.fi/~paulus/asid_protocol.txt
14
; by Jouni Paulus (jobe@iki.fi)
15
;
16
; The biggest collection of SID files can be found here:
17
; http://www.hvsc.c64.org/
18
;
19
; This include file provides following functions:
20
;    o SIDPLAY_Init:     initializes the player
21
;    o SIDPLAY_Handler:  see function header
22
;
23
; NOTE: some registers have to be inserted in app_defines.h to get this
24
;       parser working:
25
;
26
;SIDPLAY_STATE		EQU	0x0140	; the SysEx state
27
;SIDPLAY_CMD		EQU	0x0141	; the SysEx command
28
;SIDPLAY_DATA_CTR	EQU	0x0142	; the SysEx Data counter
29
;SIDPLAY_REG_CTR	EQU	0x0143	; the SID register counter
30
;SIDPLAY_BUFFER		EQU	0x0144	; the mask/msb buffer (8 bytes)
31
;SIDPLAY_BUFFER_END	EQU	0x014b
32
;
33
;       they have to be located to free register addresses!
34
;
35
; ==========================================================================
36
;
37
;  Copyright 1998-2007 Thorsten Klose (tk@midibox.org)
38
;  Licensed for personal non-commercial use only.
39
;  All other rights reserved.
40
;
41
; ==========================================================================
42
 
43
;; --------------------------------------------------------------------------
44
;;  FUNCTION: SIDPLAY_Init
45
;;  DESCRIPTION: This function initializes the SIDplayer
46
;;  IN:   -
47
;;  OUT:  -
48
;;  USES: -
49
;; --------------------------------------------------------------------------
50
SIDPLAY_Init
51
	SET_BSR	SIDPLAY_STATE
52
	clrf	SIDPLAY_STATE, BANKED
53
	clrf	SIDPLAY_CMD, BANKED
54
 
55
	;; disable SID player by default (will be enabled once first stream has been received)
56
	bcf	SID_STAT, SID_STAT_SIDPLAYER
57
	bcf	SID_STAT, SID_STAT_SIDPLAYER_CS_DISABLE
58
 
59
	return
60
 
61
 
62
;; --------------------------------------------------------------------------
63
;;  FUNCTION: SIDPLAY_Enable
64
;;  DESCRIPTION: This function enables the SIDplayer
65
;;  IN:   -
66
;;  OUT:  -
67
;;  USES: -
68
;; --------------------------------------------------------------------------
69
SIDPLAY_Enable
70
	;; enable SID player mode
71
	bsf	SID_STAT, SID_STAT_SIDPLAYER
72
	bsf	SID_STAT, SID_STAT_SIDPLAYER_CS_DISABLE
73
	;; (SID_STAT_SIDPLAYER_CS_DISABLE status will be determined again in USER_Tick)
74
 
75
	;; init LCD
76
	call	SIDPLAY_InitLCD
77
 
78
	;; clear LED matrix
79
	lfsr	FSR1, CS_MENU_MATRIX_BEGIN
80
	clrf	PRODL
81
SIDPLAY_Enable_InitMatrixLoop
82
	clrf	POSTINC1
83
	incf	PRODL, F
84
	BRA_IFCLR PRODL, 3, ACCESS, SIDPLAY_Enable_InitMatrixLoop
85
 
86
#if 0
87
	;; reset SID
88
	goto	SID_SR_Init
89
#else
90
	;; (don't reset SID --- this leads to misbehaviour when ASIDXP restarts a .sid)
91
	return
92
#endif
93
 
94
 
95
;; --------------------------------------------------------------------------
96
;;  FUNCTION: SIDPLAY_Disable
97
;;  DESCRIPTION: This function disables the SIDplayer
98
;;  IN:   -
99
;;  OUT:  -
100
;;  USES: -
101
;; --------------------------------------------------------------------------
102
SIDPLAY_Disable
103
	;; disable SID player mode
104
	bcf	SID_STAT, SID_STAT_SIDPLAYER
105
	bcf	SID_STAT, SID_STAT_SIDPLAYER_CS_DISABLE
106
 
107
	;; re-initialize display
108
	bsf	CS_STAT, CS_STAT_DISPLAY_INIT_REQ
109
 
110
	;; init patch
111
	goto	SID_PATCH_Init
112
 
113
 
114
;; --------------------------------------------------------------------------
115
;;  FUNCTION: SIDPLAY_InitLCD
116
;;  DESCRIPTION: This function initializes the LCD in SIDplayer mode
117
;;  IN:   -
118
;;  OUT:  -
119
;;  USES: -
120
;; --------------------------------------------------------------------------
121
SIDPLAY_HEADER_STR STRING 20, 0x00, "SIDplayer Mode      "
122
SIDPLAY_InitLCD
123
	;; don't clear LCD (takes longer than overwriting characters)
124
	TABLE_ADDR SIDPLAY_HEADER_STR
125
	call	MIOS_LCD_PrintString
126
 
127
SIDPLAY_InitLCD_LowerLineOnly
128
	movlw	0x40
129
	call	MIOS_LCD_CursorSet
130
	movlw	20
131
	call	SID_LCD_PrintSpaces
132
 
133
	movlw	0x40
134
	goto	MIOS_LCD_CursorSet
135
 
136
;; --------------------------------------------------------------------------
137
;;  FUNCTION: SIDPLAY_NoCSMessage
138
;;  DESCRIPTION: Message print when CS function used in SIDPLAY mode
139
;;  IN:   -
140
;;  OUT:  -
141
;;  USES: -
142
;; --------------------------------------------------------------------------
143
SIDPLAY_NOCS_MSG_STR STRING 18, 0x40, "Press MENU to exit"
144
SIDPLAY_NoCSMessage
145
	TABLE_ADDR SIDPLAY_NOCS_MSG_STR
146
	call	MIOS_LCD_PrintString
147
	movlw	0x40
148
	goto	MIOS_LCD_MessageStart
149
 
150
 
151
;; --------------------------------------------------------------------------
152
;;  FUNCTION: SIDPLAY_Handler
153
;;  DESCRIPTION: This function parses the incoming stream for ASID commands
154
;;  and forwards register changes to the MBHP_SID module.
155
;;  This function should be called from USER_MPROC_NotifyReceivedByte
156
;;  to forward the incoming byte
157
;;
158
;;  The coding is described under http://sammal.ton.tut.fi/~paulus/asid_protocol.txt
159
;;
160
;;  IN:   incoming MIDI byte in WREG
161
;;  OUT:  ZERO flag set if SID player active
162
;;  USES: -
163
;; --------------------------------------------------------------------------
164
SIDPLAY_Handler
165
	;; store incoming byte in MIOS_PARAMETER1
166
	movwf	MIOS_PARAMETER1
167
 
168
	;; ignore realtime events (which can be sent in between other events)
169
	movlw	0xf8
170
	cpfslt	MIOS_PARAMETER1, ACCESS
171
	rgoto SIDPLAY_Handler_End
172
 
173
	;; use banked accesses, select bank where SIDPLAY_STATE has been located
174
	;; (allows to move the SIDPLAY_* addresses above 0x7f)
175
	SET_BSR	SIDPLAY_STATE
176
 
177
	;; clear state if status byte (like 0xf0 or 0xf7...)
178
	btfsc	MIOS_PARAMETER1, 7
179
	clrf	SIDPLAY_STATE, BANKED
180
 
181
	;; check SysEx sequence (SIDPLAY_STATE[1:0] used as byte counter here)
182
	movf	SIDPLAY_STATE, W, BANKED
183
	andlw	0x03
184
	JUMPTABLE_2BYTES_UNSECURE	; 4 states
185
	rgoto	SIDPLAY_Handler_Syx0	; checks for 0xf0
186
	rgoto	SIDPLAY_Handler_Syx1	; checks for 0x2d
187
	rgoto	SIDPLAY_Handler_GetCmd	; checks for <command>
188
	rgoto	SIDPLAY_Handler_GetData ; receives the <data>
189
 
190
	;; 0xf7 (or any other status message which is < 0xf8) will reset SIDPLAY_STATE
191
 
192
SIDPLAY_Handler_Syx0	; checks for 0xf0
193
	movlw	0xf0
194
	rgoto	SIDPLAY_Handler_Syx_Check
195
SIDPLAY_Handler_Syx1	; checks for 0x2d
196
	movlw	0x2d
197
	;; 	rgoto	SIDPLAY_Handler_Syx_Check
198
SIDPLAY_Handler_Syx_Check
199
	cpfseq	MIOS_PARAMETER1, ACCESS
200
	rgoto SIDPLAY_Handler_Syx_Inv
201
 
202
	;; if byte matches, increment the state number and exit handler
203
SIDPLAY_Handler_Syx_Matched
204
	incf	SIDPLAY_STATE, F, BANKED
205
	rgoto	SIDPLAY_Handler_End
206
 
207
	;; if byte doesn't match, clear state number and exit handler
208
SIDPLAY_Handler_Syx_Inv
209
	clrf	SIDPLAY_STATE, BANKED
210
	rgoto	SIDPLAY_Handler_End
211
 
212
 
213
SIDPLAY_Handler_GetCmd ; gets the command
214
	;; increment state - next time we will continue at GetData
215
	incf	SIDPLAY_STATE, F, BANKED
216
	;; clear data counter
217
	clrf	SIDPLAY_DATA_CTR, BANKED
218
	;; copy MIDI input to CMD
219
	movf	MIOS_PARAMETER1, W
220
	movwf	SIDPLAY_CMD, BANKED
221
	xorlw	0x4c
222
	bz	SIDPLAY_Handler_InitStart
223
	xorlw	0x4d ^ 0x4c
224
	bz	SIDPLAY_Handler_InitStop
225
	xorlw	0x4e ^ 0x4d
226
	bz	SIDPLAY_Handler_InitSeq
227
	xorlw	0x4f ^ 0x4e
228
	bz	SIDPLAY_Handler_InitLCD
229
	rgoto	SIDPLAY_Handler_End
230
 
231
SIDPLAY_Handler_GetData	; handles the remaining data
232
	;; increment data counter
233
	incf	SIDPLAY_DATA_CTR, F, BANKED
234
 
235
	;; branch depending on command
236
	movf	SIDPLAY_CMD, W, BANKED
237
	xorlw	0x4c
238
	bz	SIDPLAY_Handler_CmdStart
239
	xorlw	0x4d ^ 0x4c
240
	bz	SIDPLAY_Handler_CmdStop
241
	xorlw	0x4e ^ 0x4d
242
	bz	SIDPLAY_Handler_CmdSeq
243
	xorlw	0x4f ^ 0x4e
244
	bz	SIDPLAY_Handler_CmdLCD
245
	rgoto	SIDPLAY_Handler_End
246
 
247
	;; ------------------------------------------------------------------
248
SIDPLAY_Handler_InitStart
249
	;; initialize player
250
	rcall	SIDPLAY_Enable
251
	rgoto	SIDPLAY_Handler_End
252
 
253
SIDPLAY_Handler_CmdStart
254
	rgoto	SIDPLAY_Handler_End
255
 
256
	;; ------------------------------------------------------------------
257
SIDPLAY_Handler_InitStop
258
	;; disable player
259
	rcall	SIDPLAY_Disable
260
	rgoto	SIDPLAY_Handler_End
261
 
262
SIDPLAY_Handler_CmdStop
263
	rgoto	SIDPLAY_Handler_End
264
 
265
	;; ------------------------------------------------------------------
266
SIDPLAY_Handler_InitLCD
267
	movlw	0x40
268
	call	MIOS_LCD_CursorSet
269
 
270
	;; ensure that SID player is properly initialized (some players don't send start command!)
271
	BRA_IFSET SID_STAT, SID_STAT_SIDPLAYER, ACCESS, SIDPLAY_Handler_InitLCD_SP_1
272
SIDPLAY_Handler_InitLCD_SP_0
273
	rcall	SIDPLAY_Enable			; (will also initialize the LCD)
274
	rgoto	SIDPLAY_Handler_InitLCD_SP_C
275
SIDPLAY_Handler_InitLCD_SP_1
276
	rcall	SIDPLAY_InitLCD_LowerLineOnly	; always clear lower line to remove artifacts
277
	;; 	rgoto	SIDPLAY_Handler_InitLCD_SP_C
278
SIDPLAY_Handler_InitLCD_SP_C
279
 
280
	rgoto	SIDPLAY_Handler_End
281
 
282
SIDPLAY_Handler_CmdLCD
283
	movf	MIOS_PARAMETER1, W
284
	call	MIOS_LCD_PrintChar
285
	rgoto	SIDPLAY_Handler_End
286
 
287
	;; ------------------------------------------------------------------
288
SIDPLAY_Handler_InitSeq
289
	;; clear register counter
290
	clrf	SIDPLAY_REG_CTR, BANKED
291
 
292
	;; ensure that SID player is properly initialized (some players don't send start command!)
293
	RCALL_IFCLR SID_STAT, SID_STAT_SIDPLAYER, ACCESS, SIDPLAY_Enable
294
 
295
	rgoto	SIDPLAY_Handler_End
296
 
297
SIDPLAY_Handler_CmdSeq
298
	;; data ctr <=8: receiving masks and msbs
299
	;; data ctr > 8: receiving data
300
	movlw	0x09
301
	cpfslt	SIDPLAY_DATA_CTR, BANKED
302
	rgoto SIDPLAY_Handler_CmdSeqD
303
SIDPLAY_Handler_CmdSeqB
304
	;; store mask/msb in buffer (8 bytes maximum)
305
	lfsr	FSR0, SIDPLAY_BUFFER
306
	decf	SIDPLAY_DATA_CTR, W, BANKED
307
	movff	MIOS_PARAMETER1, PLUSW0
308
	rgoto	SIDPLAY_Handler_End
309
 
310
SIDPLAY_Handler_CmdSeqD
311
SIDPLAY_Handler_CmdSeqDLoop
312
	;; if register counter > 0x1b, ignore next bytes
313
	movlw	0x1b + 1
314
	cpfslt	SIDPLAY_REG_CTR, BANKED
315
	rgoto SIDPLAY_Handler_End
316
 
317
	;; scan for next flag
318
	;; if mask flag set, transfer value to SID register
319
	BRA_IFSET SIDPLAY_BUFFER+0, 0, BANKED, SIDPLAY_Handler_CmdSeqDF
320
	;; else shift chain
321
	rcall	SIDPLAY_Handler_CmdSeqShift
322
	;; loop until next flag found
323
	rgoto	SIDPLAY_Handler_CmdSeqDLoop
324
 
325
SIDPLAY_Handler_CmdSeqDF
326
	;; value found:
327
	;; register offset in SIDPLAY_REG_CTR (partly decoded)
328
	;; bit 7 of register in SIDPLAY_BUFFER+4[0]
329
	;; bit 6-0 of register in MIOS_PARAMETER1
330
 
331
	;; copy MIDI In value to MIOS_PARAMETER2
332
	movff	MIOS_PARAMETER1, MIOS_PARAMETER2
333
	;; map register number to SID register address
334
	movf	SIDPLAY_REG_CTR, W, BANKED
335
	TABLE_ADDR_MUL_W SIDPLAY_Handler_CmdSeq_TAB, 1
336
	tblrd*+
337
	movf	TABLAT, W
338
	;; (note: reset line must stay 1)
339
	iorlw	0xe0
340
	movwf	MIOS_PARAMETER1
341
	;; add MSB to data word
342
	btfsc	SIDPLAY_BUFFER+4, 0, BANKED
343
	bsf	MIOS_PARAMETER2, 7
344
 
345
	;; EXTRA:
346
	;; hold ext. filter flag disabled to avoid unwanted background noise
347
	movlw	SIDx_RES_FCHN
348
	cpfseq	TABLAT, ACCESS
349
	rgoto SIDPLAY_Handler_CmdSeqDF_NGF
350
SIDPLAY_Handler_CmdSeqDF_F
351
	movlw	~(1 << 3)
352
	andwf	MIOS_PARAMETER2, F
353
SIDPLAY_Handler_CmdSeqDF_NGF
354
 
355
 
356
	;; EXTRA:
357
	;; check gate transition (0->1) to service animated level meters on LED matrix
358
	;; only if SID1 selected
359
	BRA_IFCLR SID_STAT, SID_STAT_SIDPLAYER_CS_DISABLE, ACCESS, SIDPLAY_Handler_CmdSeqDF_Cont
360
 
361
	movf	MIOS_PARAMETER1, W
362
	andlw	0x1f
363
	xorlw	SIDx_V1_CTRL
364
	bnz	SIDPLAY_Handler_CmdSeqDF_NG1
365
SIDPLAY_Handler_CmdSeqDF_G1
366
	movff	SIDL_SHADOW_BASE + 0x04, WREG
367
	andlw	0x01
368
	bnz	SIDPLAY_Handler_CmdSeqDF_NG1
369
	BRA_IFCLR MIOS_PARAMETER2, 0, ACCESS, SIDPLAY_Handler_CmdSeqDF_NG1
370
	movlw	0x3f
371
	movff	WREG, METER_VALUES0
372
	movff	WREG, METER_VALUES1
373
	rgoto	SIDPLAY_Handler_CmdSeqDF_Cont
374
SIDPLAY_Handler_CmdSeqDF_NG1
375
 
376
	xorlw	SIDx_V2_CTRL ^ SIDx_V1_CTRL
377
	bnz	SIDPLAY_Handler_CmdSeqDF_NG2
378
SIDPLAY_Handler_CmdSeqDF_G2
379
	movff	SIDL_SHADOW_BASE + 0x0b, WREG
380
	andlw	0x01
381
	bnz	SIDPLAY_Handler_CmdSeqDF_NG2
382
	BRA_IFCLR MIOS_PARAMETER2, 0, ACCESS, SIDPLAY_Handler_CmdSeqDF_NG2
383
	movlw	0x3f
384
	movff	WREG, METER_VALUES3
385
	movff	WREG, METER_VALUES4
386
	rgoto	SIDPLAY_Handler_CmdSeqDF_Cont
387
SIDPLAY_Handler_CmdSeqDF_NG2
388
 
389
	xorlw	SIDx_V3_CTRL ^ SIDx_V2_CTRL
390
	bnz	SIDPLAY_Handler_CmdSeqDF_NG3
391
SIDPLAY_Handler_CmdSeqDF_G3
392
	movff	SIDL_SHADOW_BASE + 0x12, WREG
393
	andlw	0x01
394
	bnz	SIDPLAY_Handler_CmdSeqDF_NG3
395
	BRA_IFCLR MIOS_PARAMETER2, 0, ACCESS, SIDPLAY_Handler_CmdSeqDF_NG3
396
	movlw	0x3f
397
	movff	WREG, METER_VALUES6
398
	movff	WREG, METER_VALUES7
399
	rgoto	SIDPLAY_Handler_CmdSeqDF_Cont
400
SIDPLAY_Handler_CmdSeqDF_NG3
401
 
402
SIDPLAY_Handler_CmdSeqDF_Cont
403
	;; write to SID register
404
	lfsr	FSR0, SIDL_SHADOW_BASE
405
	lfsr	FSR1, SIDR_SHADOW_BASE
406
	IRQ_DISABLE
407
	movf	MIOS_PARAMETER2, W
408
	call	SID_SR_TransferB
409
	IRQ_ENABLE
410
 
411
	;; shift chain
412
	rcall	SIDPLAY_Handler_CmdSeqShift
413
 
414
	;; waiting for next MIDI byte
415
	rgoto	SIDPLAY_Handler_End
416
 
417
 
418
	;; ---
419
	;; subroutine: shift masks/msbs
420
SIDPLAY_Handler_CmdSeqShift
421
	;; shift masks and msbs to the right - take 7bit format into account!
422
	clrc
423
	rrf	SIDPLAY_BUFFER+3, F, BANKED
424
	skpnc
425
	bsf	SIDPLAY_BUFFER+2, 7, BANKED
426
	clrc
427
	rrf	SIDPLAY_BUFFER+2, F, BANKED
428
	skpnc
429
	bsf	SIDPLAY_BUFFER+1, 7, BANKED
430
	clrc
431
	rrf	SIDPLAY_BUFFER+1, F, BANKED
432
	skpnc
433
	bsf	SIDPLAY_BUFFER+0, 7, BANKED
434
	clrc
435
	rrf	SIDPLAY_BUFFER+0, F, BANKED
436
 
437
	;; shift masks and msbs to the right
438
	clrc
439
	rrf	SIDPLAY_BUFFER+7, F, BANKED
440
	skpnc
441
	bsf	SIDPLAY_BUFFER+6, 7, BANKED
442
	clrc
443
	rrf	SIDPLAY_BUFFER+6, F, BANKED
444
	skpnc
445
	bsf	SIDPLAY_BUFFER+5, 7, BANKED
446
	clrc
447
	rrf	SIDPLAY_BUFFER+5, F, BANKED
448
	skpnc
449
	bsf	SIDPLAY_BUFFER+4, 7, BANKED
450
	clrc
451
	rrf	SIDPLAY_BUFFER+4, F, BANKED
452
 
453
	;; increment register number
454
	incf	SIDPLAY_REG_CTR, F, BANKED
455
 
456
	return
457
 
458
	;; ------------------------------------------------------------------
459
SIDPLAY_Handler_End
460
	return
461
 
462
	;; ---
463
	;; map register number to SID register address
464
SIDPLAY_Handler_CmdSeq_TAB
465
	db	0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0c, 0x0d, 0x0e, 0x0f
466
	db	0x10, 0x11, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x04, 0x0b, 0x12, 0x04, 0x0b, 0x12