Subversion Repositories svn.mios

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
178 tk 1
; $Id: midi.asm 178 2008-03-08 12:08:54Z tk $
2
;
3
;  MIDI IO Routines
4
;
5
; ==========================================================================
6
;
7
;  Copyright 2006 Thorsten Klose (tk@midibox.org)
8
;  Licensed for personal non-commercial use only.
9
;  All other rights reserved.
10
; 
11
; ==========================================================================
12
 
13
    list    p=16f88
14
    radix   dec
15
#include <p16f88.inc>
16
#include "macros.inc"
17
#include "globals.inc"
18
 
19
; ==========================================================================
20
 
21
    ;; export lables
22
    global  MIDI_Init
23
 
24
    global  MIDI_RxBufferUsed
25
    global  MIDI_RxBufferFree
26
    global  MIDI_RxBufferPut
27
    global  MIDI_RxBufferGet
28
 
29
    global  MIDI_TxBufferUsed
30
    global  MIDI_TxBufferFree
31
    global  MIDI_TxBufferPut
32
    global  MIDI_TxBufferGet
33
 
34
    global  MIDI_TxBufferFlush
35
    global  MIDI_TxSendDirect
36
 
37
    global  MIDI_LEDS_Handler
38
 
39
    global  MIDI_TX_BUFFER_HEAD ; (for fast access from IRQ handler)
40
    global  MIDI_TX_BUFFER_TAIL
41
 
42
; ==========================================================================
43
 
44
gpr0            udata
45
MIDI_RX_BUFFER_TMP  res 1
46
MIDI_RX_BUFFER_HEAD res 1
47
MIDI_RX_BUFFER_TAIL res 1
48
MIDI_RX_BUFFER_CTR  res 1
49
MIDI_TX_BUFFER_TMP  res 1
50
MIDI_TX_BUFFER_HEAD res 1
51
MIDI_TX_BUFFER_TAIL res 1
52
MIDI_TX_BUFFER_CTR  res 1
53
 
54
LED_TX_CTR      res 1
55
LED_RX_CTR      res 1
56
 
57
gpr2            udata   0x110
58
#define MIDI_RX_BUFFER_SIZE 0x60
59
MIDI_RX_BUFFER      res MIDI_RX_BUFFER_SIZE
60
 
61
#define MIDI_TX_BUFFER_SIZE 0x60
62
gpr3            udata   0x190
63
MIDI_TX_BUFFER      res MIDI_TX_BUFFER_SIZE
64
 
65
 
66
; ==========================================================================
67
MIDI    code
68
; ==========================================================================
69
 
70
;; --------------------------------------------------------------------------
71
;;  FUNCTION: MIDI_Init
72
;;  DESCRIPTION: initialises the MIDI interface: baudrate will be set,
73
;;  Rx and Tx buffer will be emptied
74
;;  IN:   -
75
;;  OUT:  -
76
;;  USES: -
77
;; --------------------------------------------------------------------------
78
MIDI_Init
79
MIDI_Init_MIDIBaudrate
80
    SWITCHBANK_0_1              ; set baudrate to 31250 baud
81
    movlw   (1 << TXEN)
82
    movwf   TXSTA
83
#if INTERNAL_OSC
84
    movlw   0x03        ; 31250 baud @8MHz
85
#else
86
    movlw   0x09        ; 31250 baud @20MHz
87
#endif
88
    movwf   SPBRG
89
    SWITCHBANK_1_0
90
 
91
    ; Configure Receive Status and Control Register
92
        movf    RCREG, W
93
    movlw   (1 << SPEN) | (1 << CREN)
94
    movwf   RCSTA
95
 
96
    ; initialize ringbuffers
97
    clrf    MIDI_RX_BUFFER_TAIL
98
    clrf    MIDI_RX_BUFFER_HEAD
99
    clrf    MIDI_RX_BUFFER_CTR
100
 
101
    clrf    MIDI_TX_BUFFER_TAIL
102
    clrf    MIDI_TX_BUFFER_HEAD
103
    clrf    MIDI_TX_BUFFER_CTR
104
 
105
    return
106
 
107
;; --------------------------------------------------------------------------
108
;;  FUNCTION: MIDI_RxBufferUsed
109
;;  DESCRIPTION: returns number of used bytes in receive buffer
110
;;  IN:   -
111
;;  OUT:  number of used bytes in WREG
112
;;  USES: -
113
;;  EXAMPLE:
114
;;
115
;;  ;; branch if something has been received via MIDI
116
;;  call    MIDI_RxBufferUsed
117
;;  bnz ReceivedSomething
118
;; 
119
;; --------------------------------------------------------------------------
120
MIDI_RxBufferUsed
121
    movf    MIDI_RX_BUFFER_CTR, W
122
    return
123
 
124
;; --------------------------------------------------------------------------
125
;;  FUNCTION: MIDI_RxBufferFree
126
;;  DESCRIPTION: returns number of free bytes in receive buffer
127
;;  IN:   -
128
;;  OUT:  number of free bytes in WREG
129
;;  USES: -
130
;;  EXAMPLE:
131
;;
132
;;  ;; put a MIDI byte into the Rx Buffer if it isn't full
133
;;  call    MIDI_RxBufferFree
134
;;  bz  BufferIsFull
135
;;  movlw   0xf8    ; (MIDI Clock)
136
;;  call    MIDI_RxBufferPut
137
;;
138
;; --------------------------------------------------------------------------
139
MIDI_RxBufferFree
140
    movf    MIDI_RX_BUFFER_CTR, W
141
    sublw   MIDI_RX_BUFFER_SIZE-1
142
    return
143
 
144
;; --------------------------------------------------------------------------
145
;;  FUNCTION: MIDI_RxBufferPut
146
;;  DESCRIPTION: puts a byte onto the receive buffer
147
;;  IN:   byte in WREG
148
;;  OUT:  -
149
;;  USES: FSR
150
;;  EXAMPLE:
151
;;
152
;;  ;; put a MIDI byte into the Rx Buffer if it isn't full
153
;;  movlw   0xf8    ; (MIDI Clock)
154
;;  call    MIDI_RxBufferPut
155
;;
156
;; --------------------------------------------------------------------------
157
MIDI_RxBufferPut
158
    movwf   MIDI_RX_BUFFER_TMP      ; save byte which should be sent
159
 
160
    incf    MIDI_RX_BUFFER_TAIL, W      ; increment tail ptr, wrap if end of buffer reached
161
    xorlw   MIDI_RX_BUFFER_SIZE
162
    skpz
163
    xorlw   MIDI_RX_BUFFER_SIZE     ; XOR back to old value
164
    movwf   FSR
165
    xorwf   MIDI_RX_BUFFER_HEAD, W
166
    skpnz
167
    return                  ; avoid overrun!
168
 
169
    movf    FSR, W              ; prepare buffer pointer
170
    movwf   MIDI_RX_BUFFER_TAIL
171
    addlw   LOW(MIDI_RX_BUFFER)
172
    movwf   FSR
173
    movf    MIDI_RX_BUFFER_TMP, W       ; push byte onto buffer
174
    SWITCH_FSR_UPPER
175
    movwf   INDF
176
    SWITCH_FSR_LOWER
177
    incf    MIDI_RX_BUFFER_CTR, F
178
 
179
    ;; trigger LED
180
    movlw   MIDI_LEDS_RXTX_DELAY
181
    movwf   LED_RX_CTR
182
 
183
    return
184
 
185
;; --------------------------------------------------------------------------
186
;;  FUNCTION: MIDI_RxBufferGet
187
;;  DESCRIPTION: gets a byte from the receive buffer
188
;;  IN:   -
189
;;  OUT:  byte in WREG
190
;;  USES: FSR
191
;;  EXAMPLE:
192
;;
193
;;  ;; get a MIDI byte from the Rx Buffer if something has been received
194
;;  call    MIDI_RxBufferUsed
195
;;  bz  NothingReceived
196
;;  call    MIDI_RxBufferGet
197
;;
198
;; --------------------------------------------------------------------------
199
MIDI_RxBufferGet
200
    incf    MIDI_RX_BUFFER_HEAD, F
201
    movf    MIDI_RX_BUFFER_HEAD, W
202
    xorlw   MIDI_RX_BUFFER_SIZE
203
    skpnz
204
    clrf    MIDI_RX_BUFFER_HEAD
205
 
206
    movf    MIDI_RX_BUFFER_HEAD, W
207
    addlw   LOW(MIDI_RX_BUFFER)
208
    movwf   FSR
209
    SWITCH_FSR_UPPER
210
    movf    INDF, W
211
    SWITCH_FSR_LOWER
212
    decf    MIDI_RX_BUFFER_CTR, F
213
    return
214
 
215
;; --------------------------------------------------------------------------
216
;;  FUNCTION: MIDI_TxBufferUsed
217
;;  DESCRIPTION: returns number of used bytes in buffer
218
;;  IN:   -
219
;;  OUT:  number of used bytes in WREG
220
;;  USES: -
221
;;  EXAMPLE:
222
;;
223
;;  ;; branch if something has been put into the Tx Buffer
224
;;  call    MIDI_TxBufferUsed
225
;;  bz  ReceivedSomething
226
;; 
227
;; --------------------------------------------------------------------------
228
MIDI_TxBufferUsed
229
    movf    MIDI_TX_BUFFER_CTR, W
230
    return
231
 
232
;; --------------------------------------------------------------------------
233
;;  FUNCTION: MIDI_TxBufferFree
234
;;  DESCRIPTION: returns number of free bytes in transmit buffer
235
;;  IN:   -
236
;;  OUT:  number of free bytes in WREG
237
;;  USES: -
238
;;  EXAMPLE:
239
;;
240
;;  ;; put a MIDI byte into the Tx Buffer if it isn't full
241
;;  call    MIDI_TxBufferFree
242
;;  bz  BufferIsFull
243
;;  movlw   0xf8    ; (MIDI Clock)
244
;;  call    MIDI_TxBufferPut
245
;;
246
;; --------------------------------------------------------------------------
247
MIDI_TxBufferFree
248
    movf    MIDI_TX_BUFFER_CTR, W
249
    sublw   MIDI_TX_BUFFER_SIZE-1
250
    return
251
 
252
;; --------------------------------------------------------------------------
253
;;  FUNCTION: MIDI_TxBufferPut
254
;;  DESCRIPTION: puts a byte onto the transmit buffer.
255
;;  If Tx buffer is full, function will be suspended until one byte has been
256
;;  transmitted via MIDI
257
;;  IN:   byte in WREG
258
;;  OUT:  -
259
;;  USES: FSR
260
;;  EXAMPLE:
261
;;
262
;;  ;; put a MIDI byte into the Tx Buffer if it isn't full
263
;;  movlw   0xf8    ; (MIDI Clock)
264
;;  call    MIDI_TxBufferPut
265
;;
266
;; --------------------------------------------------------------------------
267
MIDI_TxBufferPut
268
    movwf   MIDI_TX_BUFFER_TMP      ; save byte which should be sent
269
 
270
    incf    MIDI_TX_BUFFER_TAIL, W      ; increment tail ptr, wrap if end of buffer reached
271
    xorlw   MIDI_TX_BUFFER_SIZE
272
    skpz
273
    xorlw   MIDI_TX_BUFFER_SIZE     ; XOR back to old value
274
    movwf   FSR
275
    xorwf   MIDI_TX_BUFFER_HEAD, W
276
    bnz MIDI_TxBufferPut_Ok
277
 
278
    ;; repeat until buffer is free again
279
    IRQ_ENABLE      ; (we must ensure that interrupts are enabled!)
280
    movf    MIDI_TX_BUFFER_TMP, W
281
    goto    MIDI_TxBufferPut
282
 
283
MIDI_TxBufferPut_Ok
284
    IRQ_DISABLE             ; disable interrupts to avoid a malfunction when a Tx IRQ happens here
285
    movf    FSR, W              ; prepare buffer pointer
286
    movwf   MIDI_TX_BUFFER_TAIL
287
    addlw   LOW(MIDI_TX_BUFFER)
288
    movwf   FSR
289
    movf    MIDI_TX_BUFFER_TMP, W       ; push byte onto buffer
290
    SWITCH_FSR_UPPER
291
    movwf   INDF
292
    SWITCH_FSR_LOWER
293
    incf    MIDI_TX_BUFFER_CTR, F
294
 
295
    SWITCHBANK_0_1
296
    bsf PIE1, TXIE          ; (re-)enable transmit IRQ
297
    SWITCHBANK_1_0
298
 
299
    IRQ_ENABLE              ; enable interrupts again
300
 
301
    return
302
 
303
;; --------------------------------------------------------------------------
304
;;  FUNCTION: MIDI_TxBufferGet
305
;;  DESCRIPTION: gets a byte from the transmit buffer
306
;;  IN:   -
307
;;  OUT:  byte in WREG
308
;;  USES: FSR
309
;;  EXAMPLE:
310
;;
311
;;  ;; get a MIDI byte from the Tx Buffer if new byte is available
312
;;  call    MIDI_TxBufferUsed
313
;;  bz  NoByteAvailable
314
;;  call    MIDI_TxBufferGet
315
;;
316
;; --------------------------------------------------------------------------
317
MIDI_TxBufferGet
318
    incf    MIDI_TX_BUFFER_HEAD, F
319
    movf    MIDI_TX_BUFFER_HEAD, W
320
    xorlw   MIDI_TX_BUFFER_SIZE
321
    skpnz
322
    clrf    MIDI_TX_BUFFER_HEAD
323
 
324
    movf    MIDI_TX_BUFFER_HEAD, W
325
    addlw   LOW(MIDI_TX_BUFFER)
326
    movwf   FSR
327
 
328
    movlw   MIDI_LEDS_RXTX_DELAY    ; trigger LED
329
    movwf   LED_TX_CTR
330
 
331
    SWITCH_FSR_UPPER
332
    movf    INDF, W
333
    SWITCH_FSR_LOWER
334
    decf    MIDI_TX_BUFFER_CTR, F
335
    return
336
 
337
;; --------------------------------------------------------------------------
338
;;  FUNCTION: MIDI_TxBufferFlush
339
;;  DESCRIPTION: waits until all MIDI bytes in the Tx buffer have been transmitted
340
;;  IN:   -
341
;;  OUT:  -
342
;;  USES: FSR
343
;;  EXAMPLE:
344
;;
345
;;  ;; wait until buffer is empty, thereafter send a bunch of new bytes
346
;;  call    MIDI_TxBufferFlush
347
;;  movlw   0xf0
348
;;  call    MIDI_TxBufferPut
349
;;  ;;  ...
350
;;
351
;; --------------------------------------------------------------------------
352
MIDI_TxBufferFlush
353
    clrwdt
354
MIDI_TxBufferFlush_WaitTx
355
    call    MIDI_TxBufferUsed
356
    bnz MIDI_TxBufferFlush_WaitTx
357
    return
358
 
359
;; --------------------------------------------------------------------------
360
;;  FUNCTION: MIDI_TxSendDirect
361
;;  DESCRIPTION: sends unbuffered byte - only for debugging!
362
;;  IN:   -
363
;;  OUT:  -
364
;;  USES: -
365
;; --------------------------------------------------------------------------
366
MIDI_TxSendDirect
367
    SWITCHBANK_0_1
368
MIDI_TxSendDirect_Poll
369
    btfss   TXSTA, TRMT
370
    goto    MIDI_TxSendDirect_Poll
371
    SWITCHBANK_1_0
372
    movwf   TXREG
373
    return
374
 
375
;; --------------------------------------------------------------------------
376
;;  FUNCTION: MIDI_LEDS_Handler
377
;;  DESCRIPTION: this function should be called periodically from a timer
378
;;  or the mainloop. It decrements the Rx/Tx counters and sets the LEDs 
379
;;  depending on the counter values
380
;; --------------------------------------------------------------------------
381
MIDI_LEDS_Handler
382
 
383
MIDI_LEDS_Handler_Rx
384
    movf    LED_RX_CTR, W
385
    bz  MIDI_LEDS_Handler_RxOff
386
MIDI_LEDS_Handler_RxOn
387
    decf    LED_RX_CTR, F
388
#if LED_RX_PORT
389
    bcf LED_RX_PORT, LED_RX_PIN
390
#endif
391
    goto    MIDI_LEDS_Handler_Rx_End
392
MIDI_LEDS_Handler_RxOff
393
#if LED_RX_PORT
394
    bsf LED_RX_PORT, LED_RX_PIN
395
#endif
396
MIDI_LEDS_Handler_Rx_End
397
 
398
MIDI_LEDS_Handler_Tx
399
    movf    LED_TX_CTR, W
400
    bz  MIDI_LEDS_Handler_TxOff
401
MIDI_LEDS_Handler_TxOn
402
    decf    LED_TX_CTR, F
403
#if LED_TX_PORT
404
    bcf LED_TX_PORT, LED_TX_PIN
405
#endif
406
    goto    MIDI_LEDS_Handler_Tx_End
407
MIDI_LEDS_Handler_TxOff
408
#if LED_TX_PORT
409
    bsf LED_TX_PORT, LED_TX_PIN
410
#endif
411
MIDI_LEDS_Handler_Tx_End
412
 
413
    return
414
 
415
; ==========================================================================
416
    END