Subversion Repositories svn.mios

Rev

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

Rev Author Line No. Line
44 tk 1
// $Id: router.c 44 2008-01-30 21:39:30Z tk $
2
/*
3
 * MIDI Routing package
4
 * This file contains hooks which are called from iic_midi.asm and int_midi.asm
5
 *
6
 * ==========================================================================
7
 *
8
 *  Copyright 2006 Thorsten Klose (tk@midibox.org)
9
 *  Licensed for personal non-commercial use only.
10
 *  All other rights reserved.
11
 *
12
 * ==========================================================================
13
 */
14
 
15
/////////////////////////////////////////////////////////////////////////////
16
// Include files
17
/////////////////////////////////////////////////////////////////////////////
18
 
19
#include <cmios.h>
20
#include <pic18fregs.h>
21
 
22
#include "main.h"
23
#include "iic_midi.h"
24
#include "int_midi.h"
25
#include "router.h"
26
 
27
 
28
/////////////////////////////////////////////////////////////////////////////
29
// Global variables
30
/////////////////////////////////////////////////////////////////////////////
31
 
32
unsigned char sysex_owner;
33
 
34
 
35
// router specific flags (see bitfield declaration in router.h)
36
router_flags_t router_flags;
37
 
38
// for IIC3 input: if router_flags.IIC3_FWD_FORCE_CHN == 1, channel will be forced to a specific value
39
unsigned char router_iic3_fwd_force_channel;
40
// optional transpose of keyboard at IIC3
41
unsigned char router_iic3_fwd_transpose;
42
 
43
 
44
/////////////////////////////////////////////////////////////////////////////
45
// Local variables
46
/////////////////////////////////////////////////////////////////////////////
47
 
48
/////////////////////////////////////////////////////////////////////////////
49
// Local definitions
50
/////////////////////////////////////////////////////////////////////////////
51
#define MIDI_CHN1   0
52
#define MIDI_CHN2   1
53
#define MIDI_CHN3   2
54
#define MIDI_CHN4   3
55
#define MIDI_CHN5   4
56
#define MIDI_CHN6   5
57
#define MIDI_CHN7   6
58
#define MIDI_CHN8   7
59
#define MIDI_CHN9   8
60
#define MIDI_CHN10  9
61
#define MIDI_CHN11  10
62
#define MIDI_CHN12  11
63
#define MIDI_CHN13  12
64
#define MIDI_CHN14  13
65
#define MIDI_CHN15  14
66
#define MIDI_CHN16  15
67
 
68
/////////////////////////////////////////////////////////////////////////////
69
// This function initializes the router
70
/////////////////////////////////////////////////////////////////////////////
71
void ROUTER_Init(void) __wparam
72
{
73
  sysex_owner = PORT_NONE;
74
 
75
  // default setup
76
  router_flags.IIC2_FWD_CHN8_16 = 0;
77
 
78
  router_flags.IIC3_FWD_FORCE_CHN = 0;
79
  router_iic3_fwd_force_channel = MIDI_CHN1;
80
  router_iic3_fwd_transpose = 8; // +0
81
 
82
  router_flags.IIC3_FWD_MBSID = 0;
83
  router_flags.IIC3_FWD_MBFM = 0;
84
  router_flags.IIC3_FWD_MBSEQ = 0;
85
}
86
 
87
 
88
/////////////////////////////////////////////////////////////////////////////
89
// This function locks a receiver path if a SysEx stream is received
90
/////////////////////////////////////////////////////////////////////////////
91
unsigned char ROUTER_LockPathOnSysEx(unsigned char port, unsigned char ptype) __wparam
92
{
93
  // lock if SysEx starts or continues
94
  if( ptype == 0x04 ) {
95
    sysex_owner = port;
96
    return 1;
97
  }
98
 
99
  // only any other MIDI event (or if sysex ends): release path
100
  sysex_owner = PORT_NONE;
101
  return 0;
102
}
103
 
104
/////////////////////////////////////////////////////////////////////////////
105
// These functions are called from the MIDI parser when a new package has been
106
// received. They can be modified to customize the routing
107
//
108
// evnt0, evnt1, evnt2: the bytes of the MIDI event which has been received
109
//
110
// ptype: package type
111
//   - 0x02  two-byte system common message like MTC, Song Select, etc.
112
//   - 0x03  three-byte system common message like SSP, etc.
113
//   - 0x04  SysEx starts or continues
114
//   - 0x05  SysEx ends with following single byte
115
//   - 0x06  SysEx ends with following two bytes
116
//   - 0x07  SysEx ends with following three bytes
117
//   - 0x08  Note Off
118
//   - 0x09  Note On
119
//   - 0x0a  Poly-Key Pressure
120
//   - 0x0b  Control Change
121
//   - 0x0c  Program Change
122
//   - 0x0d  Channel Pressure
123
//   - 0x0e  Pitch Bend
124
//   - 0x0f  single byte like MIDI Clock/Start/Stop/Continue
125
/////////////////////////////////////////////////////////////////////////////
126
void ROUTER_Rx_INT0(unsigned char ptype, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
127
{
128
  // Core MIDI IN, connected to my PC
129
 
130
  // lock/release this routing path on SysEx streams
131
  ROUTER_LockPathOnSysEx(PORT_INT0, ptype);
132
 
133
  // forward data to the MIDI OUTs of all IIC slaves
134
  ROUTER_Tx_IIC0(ptype, evnt0, evnt1, evnt2);
135
  ROUTER_Tx_IIC1(ptype, evnt0, evnt1, evnt2);
136
  ROUTER_Tx_IIC2(ptype, evnt0, evnt1, evnt2);
137
  ROUTER_Tx_IIC3(ptype, evnt0, evnt1, evnt2);
138
}
139
 
140
void ROUTER_Rx_IIC0(unsigned char ptype, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
141
{
142
  // IIC0: connected to my MIDIbox SID
143
 
144
  // lock/release this routing path on SysEx streams
145
  ROUTER_LockPathOnSysEx(PORT_IIC0, ptype);
146
 
147
  // forward data to the Core MIDI OUT
148
  ROUTER_Tx_INT0(ptype, evnt0, evnt1, evnt2);
149
}
150
 
151
void ROUTER_Rx_IIC1(unsigned char ptype, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
152
{
153
  // IIC1: connected to my MIDIbox FM
154
 
155
  // lock/release this routing path on SysEx streams
156
  ROUTER_LockPathOnSysEx(PORT_IIC1, ptype);
157
 
158
  // forward data to the Core MIDI OUT
159
  ROUTER_Tx_INT0(ptype, evnt0, evnt1, evnt2);
160
}
161
 
162
void ROUTER_Rx_IIC2(unsigned char ptype, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
163
{
164
  // IIC2: connected to my MIDIbox SEQ
165
 
166
  // lock/release this routing path on SysEx streams
167
  ROUTER_LockPathOnSysEx(PORT_IIC2, ptype);
168
 
169
  // forward MIDI clock/start/stop/continue to all IIC modules
170
  if( evnt0 >= 0xf8 && evnt0 <= 0xfc ) {
171
    ROUTER_Tx_IIC0(ptype, evnt0, evnt1, evnt2);
172
    ROUTER_Tx_IIC1(ptype, evnt0, evnt1, evnt2);
173
    ROUTER_Tx_IIC2(ptype, evnt0, evnt1, evnt2);
174
    ROUTER_Tx_IIC3(ptype, evnt0, evnt1, evnt2);
175
  }
176
 
177
  // if IIC2_FWD_CHN8_16 flag set:
178
  if( router_flags.IIC2_FWD_CHN8_16 && (ptype >= 0x08 && ptype <= 0x0e) && ((evnt0 & 0x0f) >= MIDI_CHN9) ) {
179
    // directly forward MIDI channel #9..#16 messages to MIDIbox SID and MIDIbox FM only
180
    ROUTER_Tx_IIC0(ptype, evnt0, evnt1, evnt2);
181
    ROUTER_Tx_IIC1(ptype, evnt0, evnt1, evnt2);
182
  } else {
183
    // forward all other events to the Core MIDI OUT
184
    ROUTER_Tx_INT0(ptype, evnt0, evnt1, evnt2);
185
  }
186
}
187
 
188
void ROUTER_Rx_IIC3(unsigned char ptype, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
189
{
190
  unsigned char transposed_note;
191
 
192
  // IIC3: connected to my Yamaha AN1x
193
 
194
  // lock/release this routing path on SysEx streams
195
  ROUTER_LockPathOnSysEx(PORT_IIC3, ptype);
196
 
197
  if( ptype >= 0x08 && ptype <= 0x0e ) {
198
 
199
    // check if channel should be forced to specific value
200
    if( router_flags.IIC3_FWD_FORCE_CHN ) {
201
      evnt0 = (evnt0 & 0xf0) | (router_iic3_fwd_force_channel & 0xf);
202
    }
203
 
204
    // check if note should be transposed
205
    if( router_iic3_fwd_transpose != 8 && ptype <= 0x09 ) {
206
      if( router_iic3_fwd_transpose >= 8 ) {
207
    evnt1 += (router_iic3_fwd_transpose-8)*12;
208
    // if value >= 0x80, decrement 12 until we have reached the range <= 0x7f again
209
    while( evnt1 & 0x80 ) evnt1 -= 12;
210
      } else {
211
    evnt1 -= (8-router_iic3_fwd_transpose)*12;
212
    // if value < 0, add 12 until we have reached the range >= 0 again
213
    while( evnt1 & 0x80 ) evnt1 += 12;
214
      }
215
    }
216
 
217
    if( router_flags.IIC3_FWD_MBSID )
218
      ROUTER_Tx_IIC0(ptype, evnt0, evnt1, evnt2);
219
 
220
    if( router_flags.IIC3_FWD_MBFM )
221
      ROUTER_Tx_IIC1(ptype, evnt0, evnt1, evnt2);
222
 
223
    if( router_flags.IIC3_FWD_MBSEQ )
224
      ROUTER_Tx_IIC2(ptype, evnt0, evnt1, evnt2);
225
  }
226
 
227
  // forward data (also) to the Core MIDI OUT
228
#if 1
229
  // of no FE
230
  if( evnt0 != 0xfe )
231
#endif
232
    if( !router_flags.IIC3_FWD_MBSID && !router_flags.IIC3_FWD_MBFM && !router_flags.IIC3_FWD_MBSEQ )
233
      ROUTER_Tx_INT0(ptype, evnt0, evnt1, evnt2);
234
}
235
 
236
 
237
 
238
/////////////////////////////////////////////////////////////////////////////
239
// These functions forward a package to the appr. transmit function in 
240
// int_midi.asm and iic_midi.asm
241
//
242
// ptype: package type (see description of ROUTER_Rx_*)
243
// evnt0, evnt1, evnt2: the bytes of the MIDI event which should be transmitted
244
//
245
// These functions don't need to be modified, the routing is part of the
246
// ROUTER_Rx_xx() function!
247
/////////////////////////////////////////////////////////////////////////////
248
void ROUTER_Tx_INT0(unsigned char ptype, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
249
{
250
  unsigned char retry_ctr = 0;
251
  while( (++retry_ctr != 0xff) && !INT_MIDI_Transmit(0, ptype, evnt0, evnt1, evnt2) );
252
}
253
 
254
void ROUTER_Tx_IIC0(unsigned char ptype, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
255
{
256
  unsigned char retry_ctr = 0;
257
  while( (++retry_ctr != 0xff) && !IIC_MIDI_Transmit(0, ptype, evnt0, evnt1, evnt2) );
258
}
259
 
260
void ROUTER_Tx_IIC1(unsigned char ptype, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
261
{
262
  unsigned char retry_ctr = 0;
263
  while( (++retry_ctr != 0xff) && !IIC_MIDI_Transmit(1, ptype, evnt0, evnt1, evnt2) );
264
}
265
 
266
void ROUTER_Tx_IIC2(unsigned char ptype, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
267
{
268
  unsigned char retry_ctr = 0;
269
  while( (++retry_ctr != 0xff) && !IIC_MIDI_Transmit(2, ptype, evnt0, evnt1, evnt2) );
270
}
271
 
272
void ROUTER_Tx_IIC3(unsigned char ptype, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
273
{
274
  unsigned char retry_ctr = 0;
275
  while( (++retry_ctr != 0xff) && !IIC_MIDI_Transmit(3, ptype, evnt0, evnt1, evnt2) );
276
}