Subversion Repositories svn.mios32

Rev

Rev 1771 | Rev 1806 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
182 tk 1
// $Id: seq_midi_in.c 1794 2013-05-31 19:25:43Z tk $
2
/*
3
 * MIDI IN Routines
4
 *
5
 * ==========================================================================
6
 *
7
 *  Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
8
 *  Licensed for personal non-commercial use only.
9
 *  All other rights reserved.
10
 *
11
 * ==========================================================================
12
 */
13
 
14
/////////////////////////////////////////////////////////////////////////////
15
// Include files
16
/////////////////////////////////////////////////////////////////////////////
17
 
18
#include <mios32.h>
303 tk 19
#include "tasks.h"
182 tk 20
 
1083 tk 21
#include <notestack.h>
683 tk 22
 
416 tk 23
#include "seq_ui.h"
182 tk 24
#include "seq_midi_in.h"
1219 tk 25
#include "seq_core.h"
1083 tk 26
#include "seq_cv.h"
182 tk 27
#include "seq_cc.h"
741 tk 28
#include "seq_pattern.h"
1675 tk 29
#include "seq_song.h"
473 tk 30
#include "seq_morph.h"
182 tk 31
#include "seq_core.h"
690 tk 32
#include "seq_record.h"
1219 tk 33
#include "seq_live.h"
741 tk 34
#include "seq_hwcfg.h"
35
#include "seq_file_b.h"
182 tk 36
 
37
 
38
/////////////////////////////////////////////////////////////////////////////
343 tk 39
// for optional debugging messages via DEBUG_MSG (defined in mios32_config.h)
308 tk 40
/////////////////////////////////////////////////////////////////////////////
686 tk 41
#define DEBUG_VERBOSE_LEVEL 0
308 tk 42
 
43
 
44
/////////////////////////////////////////////////////////////////////////////
182 tk 45
// Local definitions
46
/////////////////////////////////////////////////////////////////////////////
47
 
1117 tk 48
// Too complicated for the world? Pattern has to be stored before this feature is used to avoid data loss
49
#define PATCH_CHANGER_ENABLED 0
50
 
182 tk 51
// the notestack size (can be overruled in mios32_config.h)
52
#ifndef SEQ_MIDI_IN_NOTESTACK_SIZE
53
#define SEQ_MIDI_IN_NOTESTACK_SIZE 10
54
#endif
55
 
826 tk 56
#define SEQ_MIDI_IN_SECTION_CHANGER_NOTESTACK_SIZE 4
793 tk 57
#define SEQ_MIDI_IN_PATCH_CHANGER_NOTESTACK_SIZE 4
182 tk 58
 
793 tk 59
 
182 tk 60
// number of notestacks and assignments
1023 tk 61
#define BUS_NOTESTACK_NUM             3
62
#define BUS_NOTESTACK_TRANSPOSER      0
63
#define BUS_NOTESTACK_ARP_SORTED      1
64
#define BUS_NOTESTACK_ARP_UNSORTED    2
182 tk 65
 
1023 tk 66
// additional notestacks for section and patch changer
67
#define SECTION_CHANGER_NOTESTACK_NUM  4
68
#define SECTION_CHANGER_NOTESTACK_G1   0
69
#define SECTION_CHANGER_NOTESTACK_G2   1
70
#define SECTION_CHANGER_NOTESTACK_G3   2
71
#define SECTION_CHANGER_NOTESTACK_G4   3
182 tk 72
 
1023 tk 73
#define PATCH_CHANGER_NOTESTACK_NUM    4
74
#define PATCH_CHANGER_NOTESTACK_G1     0
75
#define PATCH_CHANGER_NOTESTACK_G2     1
76
#define PATCH_CHANGER_NOTESTACK_G3     2
77
#define PATCH_CHANGER_NOTESTACK_G4     3
78
 
79
 
182 tk 80
/////////////////////////////////////////////////////////////////////////////
81
// Local prototypes
82
/////////////////////////////////////////////////////////////////////////////
83
 
1023 tk 84
static s32 SEQ_MIDI_IN_Receive_Note(u8 bus, u8 note, u8 velocity);
1675 tk 85
static s32 SEQ_MIDI_IN_Receive_ExtCtrlCC(u8 cc, u8 value);
86
static s32 SEQ_MIDI_IN_Receive_ExtCtrlPC(u8 value);
826 tk 87
static s32 SEQ_MIDI_IN_Receive_NoteSC(u8 note, u8 velocity);
1117 tk 88
#if PATCH_CHANGER_ENABLED
793 tk 89
static s32 SEQ_MIDI_IN_Receive_NotePC(u8 note, u8 velocity);
1117 tk 90
#endif
182 tk 91
 
92
/////////////////////////////////////////////////////////////////////////////
93
// Global variables
94
/////////////////////////////////////////////////////////////////////////////
95
 
826 tk 96
// For Transposer/Arpeggiator:
406 tk 97
// 0 disables MIDI In, 1..16 define the MIDI channel which should be used
1023 tk 98
u8 seq_midi_in_channel[SEQ_MIDI_IN_NUM_BUSSES];
457 tk 99
// which IN port should be used? (0: All)
1023 tk 100
mios32_midi_port_t seq_midi_in_port[SEQ_MIDI_IN_NUM_BUSSES];
406 tk 101
 
1023 tk 102
// lower/upper note of bus range
103
u8 seq_midi_in_lower[SEQ_MIDI_IN_NUM_BUSSES];
104
u8 seq_midi_in_upper[SEQ_MIDI_IN_NUM_BUSSES];
406 tk 105
 
1023 tk 106
// options
107
seq_midi_in_options_t seq_midi_in_options[SEQ_MIDI_IN_NUM_BUSSES];
108
 
1675 tk 109
 
110
// For External Control functions:
111
// 0 disables MIDI In, 1..16 define the MIDI channel which should be used
112
u8 seq_midi_in_ext_ctrl_channel;
113
// which IN port should be used? (0: All)
114
mios32_midi_port_t seq_midi_in_ext_ctrl_port;
1794 tk 115
// and which optional out port? (0: Off)
116
mios32_midi_port_t seq_midi_in_ext_ctrl_out_port;
1675 tk 117
// external controller assignments
118
u8 seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_NUM];
119
 
987 tk 120
// For Record function:
121
// 0 disables MIDI In, 1..16 define the MIDI channel which should be used
122
u8 seq_midi_in_rec_channel;
123
// which IN port should be used? (0: All)
124
mios32_midi_port_t seq_midi_in_rec_port;
125
 
126
 
826 tk 127
// for Sections:
128
// 0 disables MIDI In, 1..16 define the MIDI channel which should be used
129
u8 seq_midi_in_sect_channel;
130
// which IN port should be used? (0: All)
131
mios32_midi_port_t seq_midi_in_sect_port;
848 tk 132
// optional OUT port to forward octaves not taken by section selection (0: disable)
133
mios32_midi_port_t seq_midi_in_sect_fwd_port;
826 tk 134
// Starting note for section selection:
135
u8 seq_midi_in_sect_note[4];
136
 
137
 
182 tk 138
/////////////////////////////////////////////////////////////////////////////
139
// Local variables
140
/////////////////////////////////////////////////////////////////////////////
141
 
1023 tk 142
// we have three notestacks per bus: one for transposer, two other for arpeggiator
143
static notestack_t bus_notestack[SEQ_MIDI_IN_NUM_BUSSES][BUS_NOTESTACK_NUM];
144
static notestack_item_t bus_notestack_items[SEQ_MIDI_IN_NUM_BUSSES][BUS_NOTESTACK_NUM][SEQ_MIDI_IN_NOTESTACK_SIZE];
182 tk 145
 
1023 tk 146
static notestack_t section_changer_notestack[SECTION_CHANGER_NOTESTACK_NUM];
147
static notestack_item_t section_changer_notestack_items[SECTION_CHANGER_NOTESTACK_NUM][SEQ_MIDI_IN_NOTESTACK_SIZE];
148
 
149
static notestack_t patch_changer_notestack[SECTION_CHANGER_NOTESTACK_NUM];
150
static notestack_item_t patch_changer_notestack_items[SECTION_CHANGER_NOTESTACK_NUM][SEQ_MIDI_IN_NOTESTACK_SIZE];
151
 
182 tk 152
// last note which has been played
1023 tk 153
static u8 transposer_hold_note[SEQ_MIDI_IN_NUM_BUSSES];
182 tk 154
 
155
// last arp notes which have been played
1023 tk 156
static notestack_item_t arp_sorted_hold[SEQ_MIDI_IN_NUM_BUSSES][4];
157
static notestack_item_t arp_unsorted_hold[SEQ_MIDI_IN_NUM_BUSSES][4];
182 tk 158
 
741 tk 159
// for MIDI remote keyboard function
160
static u8 remote_active;
161
 
1639 tk 162
// for automatic note-stack reset
163
static u8 last_bus_received_from_loopback;
741 tk 164
 
1639 tk 165
 
182 tk 166
/////////////////////////////////////////////////////////////////////////////
167
// Initialisation
168
/////////////////////////////////////////////////////////////////////////////
169
s32 SEQ_MIDI_IN_Init(u32 mode)
170
{
1023 tk 171
  int bus;
600 tk 172
 
826 tk 173
  SEQ_MIDI_IN_ResetAllStacks();
174
 
600 tk 175
  // stored in global config:
1023 tk 176
  for(bus=0; bus<SEQ_MIDI_IN_NUM_BUSSES; ++bus) {
177
    seq_midi_in_channel[bus] = bus+1; // Channel #1 (0 disables MIDI IN)
178
    seq_midi_in_port[bus] = DEFAULT; // All ports
179
    seq_midi_in_lower[bus] = 0x00; // lowest note
180
    seq_midi_in_upper[bus] = 0x7f; // highest note
181
    seq_midi_in_options[bus].ALL = 0; // disable all options
182
  }
600 tk 183
 
1675 tk 184
  seq_midi_in_ext_ctrl_channel = 0; // 0 disables MIDI IN
185
  seq_midi_in_ext_ctrl_port = DEFAULT; // All ports
1794 tk 186
  seq_midi_in_ext_ctrl_out_port = 0; // off
1675 tk 187
 
188
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_MORPH] = 1;
189
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_SCALE] = 3;
190
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_PATTERN_G1] = 112;
191
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_PATTERN_G2] = 113;
192
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_PATTERN_G3] = 114;
193
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_PATTERN_G4] = 115;
194
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_SONG] = 102;
195
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_PHRASE] = 103;
196
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_BANK_G1] = 116;
197
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_BANK_G2] = 117;
198
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_BANK_G3] = 118;
199
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_BANK_G4] = 119;
200
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_ALL_NOTES_OFF] = 123;
201
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_NRPN_ENABLED] = 1;
202
  seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_PC_MODE] = SEQ_MIDI_IN_EXT_CTRL_PC_MODE_OFF;
203
 
987 tk 204
  seq_midi_in_rec_channel = 1; // Channel #1 (0 disables MIDI IN)
205
  seq_midi_in_rec_port = DEFAULT; // All ports
206
 
826 tk 207
  seq_midi_in_sect_channel = 0; // disabled by default
208
  seq_midi_in_sect_port = DEFAULT; // All ports
848 tk 209
  seq_midi_in_sect_fwd_port = DEFAULT; // 0 = disable
1023 tk 210
 
211
  int i;
826 tk 212
  for(i=0; i<4; ++i)
213
    seq_midi_in_sect_note[i] = 0x30 + 12*i;
214
 
741 tk 215
  remote_active = 0;
1639 tk 216
  last_bus_received_from_loopback = 0x00;
741 tk 217
 
600 tk 218
  return 0; // no error
219
}
220
 
221
 
222
/////////////////////////////////////////////////////////////////////////////
1675 tk 223
// Returns the name of an external controller (up to 15 chars)
224
/////////////////////////////////////////////////////////////////////////////
225
const char *SEQ_MIDI_IN_ExtCtrlStr(u8 ext_ctrl)
226
{
227
  const char* ext_ctrl_str[SEQ_MIDI_IN_EXT_CTRL_NUM] = {
228
  //<--------------->
229
    "Morph Value",
230
    "Scale",
231
    "Song Number",
232
    "Song Phrase",
233
    "Pattern G1",
234
    "Pattern G2",
235
    "Pattern G3",
236
    "Pattern G4",
237
    "Bank G1",
238
    "Bank G2",
239
    "Bank G3",
240
    "Bank G4",
241
    "All Notes Off",
242
    "NRPNs",
243
    "PrgChange Mode",
244
  };
245
 
246
  if( ext_ctrl >= SEQ_MIDI_IN_EXT_CTRL_NUM )
247
    return "Invalid Ctrl.";
248
 
249
  return ext_ctrl_str[ext_ctrl];
250
}
251
 
252
 
253
/////////////////////////////////////////////////////////////////////////////
254
// Returns the name of an external controller program change mode (up to 9 chars)
255
/////////////////////////////////////////////////////////////////////////////
256
const char *SEQ_MIDI_IN_ExtCtrlPcModeStr(u8 pc_mode)
257
{
258
  const char* ext_ctrl_pc_mode_str[SEQ_MIDI_IN_EXT_CTRL_PC_MODE_NUM] = {
259
  //<---------->
260
    "off",
261
    "Patterns",
262
    "Song",
263
    "Phrase",
264
  };
265
 
266
  if( pc_mode >= SEQ_MIDI_IN_EXT_CTRL_PC_MODE_NUM )
267
    return "UnknwnMde";
268
 
269
  return ext_ctrl_pc_mode_str[pc_mode];
270
}
271
 
272
 
273
/////////////////////////////////////////////////////////////////////////////
1794 tk 274
// since there is currently no better place (somebody could expect this function in SEQ_MIDI_OUT...)
275
/////////////////////////////////////////////////////////////////////////////
276
extern s32 SEQ_MIDI_IN_ExtCtrlSend(u8 ext_ctrl, u8 value)
277
{
278
  if( seq_midi_in_ext_ctrl_out_port && seq_midi_in_ext_ctrl_channel ) {
279
    mios32_midi_port_t port = seq_midi_in_ext_ctrl_out_port;
280
    mios32_midi_chn_t chn = seq_midi_in_ext_ctrl_channel - 1;
281
 
282
    u8 cc = seq_midi_in_ext_ctrl_asg[ext_ctrl];
283
    if( cc <= 127 ) {
284
      MUTEX_MIDIOUT_TAKE;
285
      MIOS32_MIDI_SendCC(port, chn, cc, value);
286
      MUTEX_MIDIOUT_GIVE;    
287
    }
288
 
289
    u8 pc_mode = seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_PC_MODE];
290
    if( (pc_mode == SEQ_MIDI_IN_EXT_CTRL_PC_MODE_PATTERNS && ext_ctrl >= SEQ_MIDI_IN_EXT_CTRL_PATTERN_G1 && ext_ctrl <= SEQ_MIDI_IN_EXT_CTRL_PATTERN_G4) ||
291
    (pc_mode == SEQ_MIDI_IN_EXT_CTRL_PC_MODE_SONG && ext_ctrl == SEQ_MIDI_IN_EXT_CTRL_SONG) ||
292
    (pc_mode == SEQ_MIDI_IN_EXT_CTRL_PC_MODE_PHRASE && ext_ctrl == SEQ_MIDI_IN_EXT_CTRL_PHRASE) ) {
293
      MUTEX_MIDIOUT_TAKE;
294
      MIOS32_MIDI_SendProgramChange(port, chn, value);
295
      MUTEX_MIDIOUT_GIVE;    
296
    }
297
  }
298
 
299
  return 0;
300
}
301
 
302
 
303
/////////////////////////////////////////////////////////////////////////////
826 tk 304
// resets note stacks used for transposer/arpeggiator
600 tk 305
/////////////////////////////////////////////////////////////////////////////
1675 tk 306
s32 SEQ_MIDI_IN_ResetSingleTransArpStacks(u8 bus)
600 tk 307
{
1675 tk 308
  if( bus >= SEQ_MIDI_IN_NUM_BUSSES )
309
    return -1;
310
 
1639 tk 311
  NOTESTACK_Init(&bus_notestack[bus][BUS_NOTESTACK_TRANSPOSER],
312
         NOTESTACK_MODE_PUSH_TOP,
313
         &bus_notestack_items[bus][BUS_NOTESTACK_TRANSPOSER][0],
314
         SEQ_MIDI_IN_NOTESTACK_SIZE);
182 tk 315
 
1639 tk 316
  NOTESTACK_Init(&bus_notestack[bus][BUS_NOTESTACK_ARP_SORTED],
317
         NOTESTACK_MODE_SORT,
318
         &bus_notestack_items[bus][BUS_NOTESTACK_ARP_SORTED][0],
319
         SEQ_MIDI_IN_NOTESTACK_SIZE);
182 tk 320
 
1639 tk 321
  NOTESTACK_Init(&bus_notestack[bus][BUS_NOTESTACK_ARP_UNSORTED],
322
         NOTESTACK_MODE_PUSH_TOP,
323
         &bus_notestack_items[bus][BUS_NOTESTACK_ARP_UNSORTED][0],
324
         SEQ_MIDI_IN_NOTESTACK_SIZE);
683 tk 325
 
1639 tk 326
  transposer_hold_note[bus] = 0x3c; // C-3
683 tk 327
 
1639 tk 328
  int i;
329
  for(i=0; i<4; ++i)
330
    arp_sorted_hold[bus][i].ALL = arp_unsorted_hold[bus][i].ALL = 0;
182 tk 331
 
1639 tk 332
  arp_sorted_hold[bus][0].note = arp_unsorted_hold[bus][0].note = 0x3c; // C-3
333
  arp_sorted_hold[bus][1].note = arp_unsorted_hold[bus][1].note = 0x40; // E-3
334
  arp_sorted_hold[bus][2].note = arp_unsorted_hold[bus][2].note = 0x43; // G-3
335
  arp_sorted_hold[bus][3].note = arp_unsorted_hold[bus][3].note = 0x48; // C-4
336
 
337
  return 0; // no error
338
}
339
 
340
 
341
/////////////////////////////////////////////////////////////////////////////
342
// resets note stacks used for transposer/arpeggiator
343
/////////////////////////////////////////////////////////////////////////////
344
s32 SEQ_MIDI_IN_ResetTransArpStacks(void)
345
{
346
  int bus;
347
  for(bus=0; bus<SEQ_MIDI_IN_NUM_BUSSES; ++bus) {
348
    SEQ_MIDI_IN_ResetSingleTransArpStacks(bus);
1023 tk 349
  }
350
 
182 tk 351
  return 0; // no error
352
}
353
 
354
 
355
/////////////////////////////////////////////////////////////////////////////
826 tk 356
// resets note stacks used for patch changer
357
/////////////////////////////////////////////////////////////////////////////
358
s32 SEQ_MIDI_IN_ResetChangerStacks(void)
359
{
360
  int i;
361
 
1023 tk 362
  for(i=0; i<SECTION_CHANGER_NOTESTACK_NUM; ++i)
363
    NOTESTACK_Init(&section_changer_notestack[i],
826 tk 364
           NOTESTACK_MODE_PUSH_TOP,
1023 tk 365
           &section_changer_notestack_items[i][0],
826 tk 366
           SEQ_MIDI_IN_SECTION_CHANGER_NOTESTACK_SIZE);
367
 
1023 tk 368
  for(i=0; i<PATCH_CHANGER_NOTESTACK_NUM; ++i)
369
    NOTESTACK_Init(&patch_changer_notestack[i],
826 tk 370
           NOTESTACK_MODE_PUSH_TOP,
1023 tk 371
           &patch_changer_notestack_items[i][0],
826 tk 372
           SEQ_MIDI_IN_PATCH_CHANGER_NOTESTACK_SIZE);
373
 
374
  // following operation should be atomic!
375
  u8 track;
376
  seq_core_trk_t *t = &seq_core_trk[0];
377
  MIOS32_IRQ_Disable();
378
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, ++t)
828 tk 379
    t->play_section = 0; // don't select section
826 tk 380
  MIOS32_IRQ_Enable();
381
 
382
  return 0; // no error
383
}
384
 
385
/////////////////////////////////////////////////////////////////////////////
386
// resets all note stacks
387
/////////////////////////////////////////////////////////////////////////////
388
s32 SEQ_MIDI_IN_ResetAllStacks(void)
389
{
390
  s32 status = 0;
391
 
392
  status |= SEQ_MIDI_IN_ResetTransArpStacks();
393
  status |= SEQ_MIDI_IN_ResetChangerStacks();
394
 
395
  return status;
396
}
397
 
398
 
399
/////////////////////////////////////////////////////////////////////////////
182 tk 400
// Receives a MIDI package from APP_NotifyReceivedEvent (-> app.c)
401
/////////////////////////////////////////////////////////////////////////////
402
s32 SEQ_MIDI_IN_Receive(mios32_midi_port_t port, mios32_midi_package_t midi_package)
403
{
303 tk 404
  s32 status = 0;
405
 
1023 tk 406
  // check if we should record this event
407
  u8 should_be_recorded =
1313 tk 408
    seq_record_state.ENABLED &&
1023 tk 409
    ((!seq_midi_in_rec_port || port == seq_midi_in_rec_port) &&
410
     midi_package.chn == (seq_midi_in_rec_channel-1));
304 tk 411
 
1771 tk 412
  // simplify Note On/Off handling
413
  if( midi_package.event == NoteOff ) {
414
    midi_package.event = NoteOn;
415
    midi_package.velocity = 0;
416
  }
417
 
1023 tk 418
  // search for matching ports
419
  // status[0] set if at least one port matched
420
  // status[1] set if remote function active
421
  int bus;
422
  for(bus=0; bus<SEQ_MIDI_IN_NUM_BUSSES; ++bus) {
423
    // filter MIDI port (if 0: no filter, listen to all ports)
424
    if( (!seq_midi_in_port[bus] || port == seq_midi_in_port[bus]) &&
425
    midi_package.chn == (seq_midi_in_channel[bus]-1) ) {
473 tk 426
 
826 tk 427
      switch( midi_package.event ) {
1771 tk 428
      case NoteOff:
429
      case NoteOn:
742 tk 430
 
1771 tk 431
    if( midi_package.velocity == 0 ) {
432
      if( remote_active ) {
433
        if( seq_hwcfg_midi_remote.key && midi_package.note == seq_hwcfg_midi_remote.key ) {
434
          remote_active = 0;
1320 tk 435
 
1771 tk 436
          MUTEX_MIDIOUT_TAKE;
437
          DEBUG_MSG("[SEQ_MIDI_IN] MIDI remote access deactivated");
438
          MUTEX_MIDIOUT_GIVE;
1322 tk 439
 
1771 tk 440
          // send "button depressed" state to all remote functions
441
          int i;
442
          for(i=0; i<128; ++i)
443
        SEQ_UI_REMOTE_MIDI_Keyboard(i, 1); // depressed
444
        } else {
445
          SEQ_UI_REMOTE_MIDI_Keyboard(midi_package.note, 1); // depressed
1322 tk 446
        }
1023 tk 447
        status |= 2;
448
      } else {
449
        if( !should_be_recorded &&
450
        midi_package.note >= seq_midi_in_lower[bus] &&
451
        (!seq_midi_in_upper[bus] || midi_package.note <= seq_midi_in_upper[bus]) ) {
1320 tk 452
 
453
          if( !seq_midi_in_options[bus].MODE_PLAY ) {
1023 tk 454
#if 0
455
        // octave normalisation - too complicated for normal users...
456
        mios32_midi_package_t p = midi_package;
457
        if( seq_midi_in_lower[bus] ) { // normalize to first octave
458
          int normalized_note = 0x30 + p.note - ((int)seq_midi_in_lower[bus]/12)*12;
1746 tk 459
          // ensure that note is in the 0..127 range
460
          normalized_note = SEQ_CORE_TrimNote(normalized_note, 0, 127);
1023 tk 461
          p.note = normalized_note;
462
        }
1675 tk 463
        SEQ_MIDI_IN_BusReceive(bus, p, 0);
1023 tk 464
#else
1675 tk 465
        SEQ_MIDI_IN_BusReceive(bus, midi_package, 0);
1023 tk 466
#endif
467
          }
1322 tk 468
 
469
          if( seq_midi_in_options[bus].MODE_PLAY
470
#ifdef MBSEQV4L
1771 tk 471
          || (seq_record_options.FWD_MIDI && !seq_record_state.ENABLED) // MBSEQV4L: forward event if FWD_MIDI enabled but not in record page
1322 tk 472
#endif
473
          ) {
474
        SEQ_LIVE_PlayEvent(SEQ_UI_VisibleTrackGet(), midi_package);
475
          }
1771 tk 476
 
1023 tk 477
          status |= 1;
478
        }
479
      }
1771 tk 480
    } else {
481
      if( remote_active )
482
        SEQ_UI_REMOTE_MIDI_Keyboard(midi_package.note, 0);
483
      else {
484
        if( seq_hwcfg_midi_remote.key && midi_package.note == seq_hwcfg_midi_remote.key ) {
485
          MUTEX_MIDIOUT_TAKE;
486
          DEBUG_MSG("[SEQ_MIDI_IN] MIDI remote access activated");
487
          MUTEX_MIDIOUT_GIVE;
488
          remote_active = 1;
489
          status |= 2;
490
        } else {
491
          if( !should_be_recorded &&
492
          midi_package.note >= seq_midi_in_lower[bus] &&
493
          (!seq_midi_in_upper[bus] || midi_package.note <= seq_midi_in_upper[bus]) ) {
494
 
495
        if( !seq_midi_in_options[bus].MODE_PLAY ) {
496
#if 0
497
          // octave normalisation - too complicated for normal users...
498
          mios32_midi_package_t p = midi_package;
499
          if( seq_midi_in_lower[bus] ) { // normalize to first octave
500
            int normalized_note = 0x30 + p.note - ((int)seq_midi_in_lower[bus]/12)*12;
501
            // ensure that note is in the 0..127 range
502
            normalized_note = SEQ_CORE_TrimNote(normalized_note, 0, 127);
503
            p.note = normalized_note;
504
          }
505
          SEQ_MIDI_IN_BusReceive(bus, p, 0);
506
#else
507
          SEQ_MIDI_IN_BusReceive(bus, midi_package, 0);
508
#endif
509
        }
510
 
511
        if( seq_midi_in_options[bus].MODE_PLAY
512
#ifdef MBSEQV4L
513
            || (seq_record_options.FWD_MIDI && !seq_record_state.ENABLED) // MBSEQV4L: forward event if FWD_MIDI enabled but not in record page
514
#endif
515
            ) {
516
          SEQ_LIVE_PlayEvent(SEQ_UI_VisibleTrackGet(), midi_package);
517
        }
518
 
519
        status |= 1;
520
          }
521
        }
522
      }
1023 tk 523
    }
524
    break;
525
 
526
      case CC:
527
    if( !should_be_recorded ) {
1320 tk 528
 
1322 tk 529
      if( !seq_midi_in_options[bus].MODE_PLAY ) {
1675 tk 530
        SEQ_MIDI_IN_BusReceive(bus, midi_package, 0);
1322 tk 531
      }
532
 
1320 tk 533
      if( seq_midi_in_options[bus].MODE_PLAY
534
#ifdef MBSEQV4L
535
          || (seq_record_options.FWD_MIDI && !seq_record_state.ENABLED) // MBSEQV4L: forward event if FWD_MIDI enabled but not in record page
536
#endif
537
          ) {
1219 tk 538
        SEQ_LIVE_PlayEvent(SEQ_UI_VisibleTrackGet(), midi_package);
1320 tk 539
      }
540
 
1023 tk 541
    }
542
    status |= 1;
543
    break;
544
 
545
      default:
1320 tk 546
    if( seq_midi_in_options[bus].MODE_PLAY
547
#ifdef MBSEQV4L
548
        || (seq_record_options.FWD_MIDI && !seq_record_state.ENABLED) // MBSEQV4L: forward event if FWD_MIDI enabled but not in record page
549
#endif
550
        ) {
1219 tk 551
      SEQ_LIVE_PlayEvent(SEQ_UI_VisibleTrackGet(), midi_package);
1023 tk 552
    }
826 tk 553
      }
554
    }
555
  }
556
 
1023 tk 557
 
987 tk 558
  // record function
1023 tk 559
  if( !(status & 2) && should_be_recorded ) {
987 tk 560
    SEQ_RECORD_Receive(midi_package, SEQ_UI_VisibleTrackGet());
561
  }
562
 
1675 tk 563
  // External Control
564
  if( !(status & 2) &&
565
      (seq_midi_in_ext_ctrl_port && port == seq_midi_in_ext_ctrl_port &&
566
       midi_package.chn == (seq_midi_in_ext_ctrl_channel-1)) ) {
567
 
568
    switch( midi_package.event ) {
569
      case CC:
570
    MUTEX_MIDIIN_TAKE;
571
    SEQ_MIDI_IN_Receive_ExtCtrlCC(midi_package.cc_number, midi_package.value);
572
    MUTEX_MIDIIN_GIVE;
573
    break;
574
 
575
      case ProgramChange:
576
    MUTEX_MIDIIN_TAKE;
577
    SEQ_MIDI_IN_Receive_ExtCtrlPC(midi_package.program_change);
578
    MUTEX_MIDIIN_GIVE;
579
    break;
580
    }
581
  }
582
 
583
 
826 tk 584
  // Section Changer
1023 tk 585
  if( !(status & 2) &&
987 tk 586
      (seq_midi_in_sect_port && port == seq_midi_in_sect_port &&
587
       midi_package.chn == (seq_midi_in_sect_channel-1)) ) {
848 tk 588
    u8 forward_event = 1;
589
 
826 tk 590
    switch( midi_package.event ) {
591
      case NoteOff:
592
    MUTEX_MIDIIN_TAKE;
848 tk 593
    if( (status = SEQ_MIDI_IN_Receive_NoteSC(midi_package.note, 0x00)) >= 1 )
594
      forward_event = 0;
826 tk 595
    MUTEX_MIDIIN_GIVE;
303 tk 596
    break;
473 tk 597
 
826 tk 598
      case NoteOn:
473 tk 599
    MUTEX_MIDIIN_TAKE;
848 tk 600
    if( (status = SEQ_MIDI_IN_Receive_NoteSC(midi_package.note, midi_package.velocity)) >= 1 )
601
      forward_event = 0;
473 tk 602
    MUTEX_MIDIIN_GIVE;
603
    break;
182 tk 604
    }
848 tk 605
 
606
    if( seq_midi_in_sect_fwd_port && forward_event ) { // octave hasn't been taken, optionally forward to forwarding port
607
      MUTEX_MIDIOUT_TAKE;
608
      MIOS32_MIDI_SendPackage(seq_midi_in_sect_fwd_port, midi_package);
609
      MUTEX_MIDIOUT_GIVE;
610
    }
182 tk 611
  }
612
 
1117 tk 613
#if PATCH_CHANGER_ENABLED
826 tk 614
  // Patch Changer (currently assigned to channel+1)
1023 tk 615
  if( !(status & 2) &&
987 tk 616
      (seq_midi_in_sect_port && port == seq_midi_in_sect_port &&
617
       midi_package.chn == (seq_midi_in_sect_channel)) ) {
848 tk 618
    u8 forward_event = 1;
619
 
793 tk 620
    switch( midi_package.event ) {
621
      case NoteOff:
622
    MUTEX_MIDIIN_TAKE;
848 tk 623
    if( (status = SEQ_MIDI_IN_Receive_NotePC(midi_package.note, 0x00)) >= 1 )
624
      forward_event = 0;
793 tk 625
    MUTEX_MIDIIN_GIVE;
626
    break;
627
 
628
      case NoteOn:
629
    MUTEX_MIDIIN_TAKE;
848 tk 630
    if( (status = SEQ_MIDI_IN_Receive_NotePC(midi_package.note, midi_package.velocity)) >= 1 )
631
      forward_event = 0;
793 tk 632
    MUTEX_MIDIIN_GIVE;
633
    break;
634
    }
848 tk 635
 
636
    if( seq_midi_in_sect_fwd_port && forward_event ) { // octave hasn't been taken, optionally forward to forwarding port
637
      MUTEX_MIDIOUT_TAKE;
638
      MIOS32_MIDI_SendPackage(seq_midi_in_sect_fwd_port, midi_package);
639
      MUTEX_MIDIOUT_GIVE;
640
    }
793 tk 641
  }
826 tk 642
#endif
793 tk 643
 
303 tk 644
  return status;
182 tk 645
}
646
 
647
 
648
/////////////////////////////////////////////////////////////////////////////
1023 tk 649
// Receives a MIDI package from a loopback port (Bus1..Bus4)
650
/////////////////////////////////////////////////////////////////////////////
1675 tk 651
s32 SEQ_MIDI_IN_BusReceive(u8 bus, mios32_midi_package_t midi_package, u8 from_loopback_port)
1023 tk 652
{
653
  s32 status = 0;
654
 
1675 tk 655
  if( bus >= SEQ_MIDI_IN_NUM_BUSSES )
656
    return -1;
657
 
1639 tk 658
  if( from_loopback_port ) {
659
    last_bus_received_from_loopback |= (1 << bus);
660
  } else if( (last_bus_received_from_loopback & (1 << bus)) ) {
661
    last_bus_received_from_loopback &= ~(1 << bus);
662
    SEQ_MIDI_IN_ResetSingleTransArpStacks(bus);
663
  }
664
 
1023 tk 665
  // Access to MIDI IN functions controlled by Mutex, since this function is access
666
  // by different tasks (APP_NotifyReceivedEvent() for received MIDI events, and 
667
  // SEQ_CORE_* for loopbacks)
668
  MUTEX_MIDIIN_TAKE;
669
 
670
  switch( midi_package.event ) {
671
  case NoteOff:
672
    status = SEQ_MIDI_IN_Receive_Note(bus, midi_package.note, 0x00);
673
    break;
674
 
675
  case NoteOn:
676
    status = SEQ_MIDI_IN_Receive_Note(bus, midi_package.note, midi_package.velocity);
677
    break;
678
 
679
  case CC:
680
    if( from_loopback_port )
681
      status = SEQ_CC_MIDI_Set(midi_package.chn, midi_package.cc_number, midi_package.value);
1675 tk 682
    else {
683
      // MIDI Remote Function?
684
      if( seq_hwcfg_midi_remote.cc && seq_hwcfg_midi_remote.cc == midi_package.cc_number ) {
685
    remote_active = midi_package.value >= 0x40;
1771 tk 686
    MUTEX_MIDIOUT_TAKE;
687
    DEBUG_MSG("[SEQ_MIDI_IN] MIDI remote access %sactivated", remote_active ? "" : "de");
688
    MUTEX_MIDIOUT_GIVE;
1675 tk 689
      }
690
    }
1023 tk 691
    break;
692
  }
693
 
694
  MUTEX_MIDIIN_GIVE;
695
 
696
  return status;
697
}
698
 
699
 
700
/////////////////////////////////////////////////////////////////////////////
182 tk 701
// If velocity == 0, Note Off event has been received, otherwise Note On event
702
/////////////////////////////////////////////////////////////////////////////
1023 tk 703
static s32 SEQ_MIDI_IN_Receive_Note(u8 bus, u8 note, u8 velocity)
182 tk 704
{
683 tk 705
  notestack_t *n;
182 tk 706
 
1023 tk 707
  if( bus >= SEQ_MIDI_IN_NUM_BUSSES )
708
    return -1;
406 tk 709
 
182 tk 710
  ///////////////////////////////////////////////////////////////////////////
711
  // Transposer
712
  ///////////////////////////////////////////////////////////////////////////
713
 
1023 tk 714
  n = &bus_notestack[bus][BUS_NOTESTACK_TRANSPOSER];
715
  if( velocity ) { // Note On
716
    NOTESTACK_Push(n, note, velocity);
717
    transposer_hold_note[bus] = n->note_items[0].note;
254 tk 718
 
1023 tk 719
    // will only be used for Bus1 and if enabled in OPT menu
1322 tk 720
    if( bus == 0
721
#ifdef MBSEQV4L
722
    && seq_core_global_transpose_enabled
723
#endif
724
    ) {
406 tk 725
      seq_core_keyb_scale_root = note % 12;
1322 tk 726
    }
1023 tk 727
  } else { // Note Off
728
    if( NOTESTACK_Pop(n, note) > 0 && n->len ) {
729
      transposer_hold_note[bus] = n->note_items[0].note;
182 tk 730
    }
1023 tk 731
  }
308 tk 732
#if DEBUG_VERBOSE_LEVEL >= 1
1023 tk 733
  DEBUG_MSG("NOTESTACK_TRANSPOSER[%d]:\n", bus);
734
  NOTESTACK_SendDebugMessage(&bus_notestack[bus][BUS_NOTESTACK_TRANSPOSER]);
406 tk 735
#endif
182 tk 736
 
737
 
738
  ///////////////////////////////////////////////////////////////////////////
739
  // Arpeggiator
740
  ///////////////////////////////////////////////////////////////////////////
741
 
1023 tk 742
  if( velocity ) { // Note On
743
    // if no note in note stack anymore, reset position of all tracks with RESTART flag set
744
    if( !bus_notestack[bus][BUS_NOTESTACK_ARP_UNSORTED].len ) {
1219 tk 745
      portENTER_CRITICAL();
1023 tk 746
      u8 track;
747
      for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
748
    if( seq_cc_trk[track].mode.RESTART ) {
749
      seq_core_trk[track].state.POS_RESET = 1;
750
    }
1219 tk 751
      portEXIT_CRITICAL();
182 tk 752
 
1023 tk 753
      // and invalidate hold stacks
754
      int i;
755
      for(i=0; i<4; ++i)
756
    arp_sorted_hold[bus][i].ALL = arp_unsorted_hold[bus][i].ALL = 0;
757
    }
182 tk 758
 
1023 tk 759
    // add to stacks
760
    NOTESTACK_Push(&bus_notestack[bus][BUS_NOTESTACK_ARP_SORTED], note, velocity);
761
    NOTESTACK_Push(&bus_notestack[bus][BUS_NOTESTACK_ARP_UNSORTED], note, velocity);
406 tk 762
 
1023 tk 763
    // copy to hold stack
764
    int i;
765
    for(i=0; i<4; ++i) {
766
      arp_unsorted_hold[bus][i].ALL = (i < bus_notestack[bus][BUS_NOTESTACK_ARP_UNSORTED].len) ? bus_notestack[bus][BUS_NOTESTACK_ARP_UNSORTED].note_items[i].ALL : 0;
767
      arp_sorted_hold[bus][i].ALL = (i < bus_notestack[bus][BUS_NOTESTACK_ARP_SORTED].len) ? bus_notestack[bus][BUS_NOTESTACK_ARP_SORTED].note_items[i].ALL : 0;
182 tk 768
    }
769
 
1023 tk 770
  } else { // Note Off
771
    // remove note from sorted/unsorted stack (not hold stacks)
772
    NOTESTACK_Pop(&bus_notestack[bus][BUS_NOTESTACK_ARP_SORTED], note);
773
    NOTESTACK_Pop(&bus_notestack[bus][BUS_NOTESTACK_ARP_UNSORTED], note);
774
  }
775
 
308 tk 776
#if DEBUG_VERBOSE_LEVEL >= 1
1023 tk 777
  DEBUG_MSG("NOTESTACK_ARP_SORTED[%d]:\n", bus);
778
  NOTESTACK_SendDebugMessage(&bus_notestack[bus][BUS_NOTESTACK_ARP_SORTED]);
779
  DEBUG_MSG("NOTESTACK_ARP_UNSORTED[%d]:\n", bus);
780
  NOTESTACK_SendDebugMessage(&bus_notestack[bus][BUS_NOTESTACK_ARP_UNSORTED]);
406 tk 781
#endif
182 tk 782
 
783
  return 0; // no error
784
}
785
 
786
 
793 tk 787
 
182 tk 788
/////////////////////////////////////////////////////////////////////////////
826 tk 789
// For Section Changes
793 tk 790
// If velocity == 0, Note Off event has been received, otherwise Note On event
791
/////////////////////////////////////////////////////////////////////////////
826 tk 792
static s32 SEQ_MIDI_IN_Receive_NoteSC(u8 note, u8 velocity)
793 tk 793
{
826 tk 794
  int octave = note / 12;
848 tk 795
  int octave_taken = 0;
826 tk 796
 
793 tk 797
  int group;
826 tk 798
  for(group=0; group<4; ++group) {
799
    if( octave == (seq_midi_in_sect_note[group] / 12) ) {
848 tk 800
      octave_taken = 1;
1023 tk 801
      notestack_t *n = &section_changer_notestack[group];
793 tk 802
 
826 tk 803
      int section = -1;
804
      if( velocity ) { // Note On
805
    NOTESTACK_Push(n, note, velocity);
806
    section = n->note_items[0].note % 12;
807
      } else { // Note Off
808
    if( NOTESTACK_Pop(n, note) > 0 && n->len ) {
809
      section = n->note_items[0].note % 12;
810
    }
811
      }
793 tk 812
 
826 tk 813
      // switch to new section if required
814
      if( section >= 0 && section < 12 ) {
828 tk 815
#if DEBUG_VERBOSE_LEVEL >= 1
816
    DEBUG_MSG("Group %d Section %d\n", group, section);
826 tk 817
#endif
818
 
819
    // following operation should be atomic!
820
    u8 track;
821
    seq_core_trk_t *t = &seq_core_trk[group*SEQ_CORE_NUM_TRACKS_PER_GROUP];
822
    MIOS32_IRQ_Disable();
823
    for(track=0; track<SEQ_CORE_NUM_TRACKS_PER_GROUP; ++track, ++t)
828 tk 824
      t->play_section = section;
826 tk 825
    MIOS32_IRQ_Enable();
826
      }
827
 
828
#if DEBUG_VERBOSE_LEVEL >= 1
829
      DEBUG_MSG("NOTESTACK_SECTION_CHANGER_G%d:\n", group+1);
830
      NOTESTACK_SendDebugMessage(n);
831
#endif
793 tk 832
    }
833
  }
834
 
848 tk 835
  return octave_taken; // return 1 if octave has been taken, otherwise 0
826 tk 836
}
837
 
838
 
839
/////////////////////////////////////////////////////////////////////////////
840
// For Patch Changes (assigned to different MIDI channel)
841
// If velocity == 0, Note Off event has been received, otherwise Note On event
842
/////////////////////////////////////////////////////////////////////////////
1117 tk 843
#if PATCH_CHANGER_ENABLED
826 tk 844
static s32 SEQ_MIDI_IN_Receive_NotePC(u8 note, u8 velocity)
845
{
846
  int octave = note / 12;
848 tk 847
  int octave_taken = 0;
826 tk 848
 
849
  int group;
850
  for(group=0; group<4; ++group) {
851
    if( octave == (seq_midi_in_sect_note[group] / 12) ) {
848 tk 852
      octave_taken = 1;
1023 tk 853
      notestack_t *n = &patch_changer_notestack[group];
826 tk 854
 
855
      int patch = -1;
856
      if( velocity ) { // Note On
857
    NOTESTACK_Push(n, note, velocity);
858
    patch = n->note_items[0].note % 12;
859
      } else { // Note Off
860
    if( NOTESTACK_Pop(n, note) > 0 && n->len ) {
861
      patch = n->note_items[0].note % 12;
862
    }
863
      }
864
 
865
      // switch to new patch if required
866
      if( patch >= 0 && patch < 8 ) {
867
    seq_pattern_t pattern = seq_pattern[group];
868
    if( pattern.num != patch ) {
869
      pattern.num = patch;
870
      pattern.DISABLED = 0;
871
      pattern.SYNCHED = 0;
872
      SEQ_PATTERN_Change(group, pattern);
873
    }
874
      }
875
 
876
#if DEBUG_VERBOSE_LEVEL >= 0
877
      DEBUG_MSG("NOTESTACK_PATCH_CHANGER_G%d:\n", group+1);
878
      NOTESTACK_SendDebugMessage(n);
879
#endif
793 tk 880
    }
881
  }
882
 
848 tk 883
  return octave_taken; // return 1 if octave has been taken, otherwise 0
793 tk 884
}
1117 tk 885
#endif
793 tk 886
 
887
/////////////////////////////////////////////////////////////////////////////
1675 tk 888
// CC has been received over external control port and channel
473 tk 889
/////////////////////////////////////////////////////////////////////////////
1675 tk 890
static s32 SEQ_MIDI_IN_Receive_ExtCtrlCC(u8 cc, u8 value)
473 tk 891
{
1117 tk 892
  static u8 nrpn_lsb = 0;
893
  static u8 nrpn_msb = 0;
741 tk 894
 
1675 tk 895
  // NRPN handling
896
  switch( cc ) {
897
  case 0x62: // NRPN LSB (selects parameter)
898
    nrpn_lsb = value;
899
    break;
1023 tk 900
 
1675 tk 901
  case 0x63: // NRPN MSB (selects track)
902
    nrpn_msb = value;
903
    break;
904
 
1794 tk 905
  case 0x06: // NRPN Value MSB (sets parameter)
1675 tk 906
    if( nrpn_msb < SEQ_CORE_NUM_TRACKS && seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_NRPN_ENABLED] )
907
      SEQ_CC_MIDI_Set(nrpn_msb, nrpn_lsb, value);
908
    break;
741 tk 909
  }
910
 
911
 
1675 tk 912
  // search for matching CCs
913
  int i;
914
  u8 *asg = (u8 *)&seq_midi_in_ext_ctrl_asg[0];
915
  for(i=0; i<SEQ_MIDI_IN_EXT_CTRL_NUM_IX_CC; ++i, ++asg) {
916
    if( cc == *asg ) {
917
      switch( i ) {
918
      case SEQ_MIDI_IN_EXT_CTRL_MORPH:
919
    SEQ_MORPH_ValueSet(value);
920
    break;
921
 
922
      case SEQ_MIDI_IN_EXT_CTRL_SCALE:
923
    seq_core_global_scale = value;
924
    break;
925
 
926
      case SEQ_MIDI_IN_EXT_CTRL_PATTERN_G1:
927
      case SEQ_MIDI_IN_EXT_CTRL_PATTERN_G2:
928
      case SEQ_MIDI_IN_EXT_CTRL_PATTERN_G3:
929
      case SEQ_MIDI_IN_EXT_CTRL_PATTERN_G4: {
930
    u8 group = i - SEQ_MIDI_IN_EXT_CTRL_PATTERN_G1;
931
    portENTER_CRITICAL();
932
    seq_pattern_t pattern = seq_pattern[group];
933
    if( value < SEQ_FILE_B_NumPatterns(pattern.bank) ) {
934
      pattern.pattern = value;
935
      pattern.DISABLED = 0;
936
      pattern.SYNCHED = 0;
937
      SEQ_PATTERN_Change(group, pattern, 0);
938
    }
939
    portEXIT_CRITICAL();
940
      } break;
941
 
942
      case SEQ_MIDI_IN_EXT_CTRL_SONG: {
943
    if( value < SEQ_SONG_NUM && value != SEQ_SONG_NumGet() ) {
944
      SEQ_SONG_Load(value);
945
    }
946
      } break;
947
 
948
      case SEQ_MIDI_IN_EXT_CTRL_PHRASE: {
949
    if( value <= 15 ) {
950
      u8 song_pos = value << 3;
951
      SEQ_SONG_PosSet(song_pos);
952
      SEQ_SONG_FetchPos(0);
953
      ui_song_edit_pos = song_pos;
954
    }
955
      } break;
956
 
957
      case SEQ_MIDI_IN_EXT_CTRL_BANK_G1:
958
      case SEQ_MIDI_IN_EXT_CTRL_BANK_G2:
959
      case SEQ_MIDI_IN_EXT_CTRL_BANK_G3:
960
      case SEQ_MIDI_IN_EXT_CTRL_BANK_G4: {
961
    u8 group = i - SEQ_MIDI_IN_EXT_CTRL_BANK_G1;
962
    portENTER_CRITICAL();
963
    seq_pattern_t pattern = seq_pattern[group];
964
    if( value < SEQ_FILE_B_NUM_BANKS ) {
965
      pattern.bank = value;
966
      pattern.DISABLED = 0;
967
      pattern.SYNCHED = 0;
968
      SEQ_PATTERN_Change(group, pattern, 0);
969
    }
970
    portEXIT_CRITICAL();
971
      } break;
972
 
973
      case SEQ_MIDI_IN_EXT_CTRL_ALL_NOTES_OFF:
974
    if( value == 0 ) {
975
      SEQ_MIDI_IN_ResetAllStacks();
976
      SEQ_CV_ResetAllChannels();
977
    }
978
      } break;
979
    }
980
  }
981
 
982
  return 0; // no error
983
}
984
 
985
 
986
/////////////////////////////////////////////////////////////////////////////
987
// PC has been received over external control port and channel
988
/////////////////////////////////////////////////////////////////////////////
989
static s32 SEQ_MIDI_IN_Receive_ExtCtrlPC(u8 value)
990
{
991
  switch( seq_midi_in_ext_ctrl_asg[SEQ_MIDI_IN_EXT_CTRL_PC_MODE] ) {
992
  case SEQ_MIDI_IN_EXT_CTRL_PC_MODE_OFF:
993
    break; // do nothing...
994
 
995
  case SEQ_MIDI_IN_EXT_CTRL_PC_MODE_PATTERNS: {
996
    portENTER_CRITICAL();
997
    // switch all patterns (don't switch banks!)
998
    int group;
999
    for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) {
741 tk 1000
      seq_pattern_t pattern = seq_pattern[group];
1001
      if( value < SEQ_FILE_B_NumPatterns(pattern.bank) ) {
1002
    pattern.pattern = value;
1003
    pattern.DISABLED = 0;
1004
    pattern.SYNCHED = 0;
1117 tk 1005
    SEQ_PATTERN_Change(group, pattern, 0);
741 tk 1006
      }
1675 tk 1007
    }
1008
    portEXIT_CRITICAL();
1009
  } break;
1010
 
1011
  case SEQ_MIDI_IN_EXT_CTRL_PC_MODE_SONG:
1012
    if( value < SEQ_SONG_NUM && value != SEQ_SONG_NumGet() ) {
1013
      SEQ_SONG_Load(value);
1014
    }
1015
    break;
741 tk 1016
 
1675 tk 1017
  case SEQ_MIDI_IN_EXT_CTRL_PC_MODE_PHRASE:
1018
    if( value <= 15 ) {
1019
      u8 song_pos = value << 3;
1020
      SEQ_SONG_PosSet(song_pos);
1021
      SEQ_SONG_FetchPos(0);
1022
      ui_song_edit_pos = song_pos;
1023
    }
1024
    break;
473 tk 1025
  }
1026
 
1027
  return 0; // no error
1028
}
1029
 
1030
 
1031
/////////////////////////////////////////////////////////////////////////////
182 tk 1032
// Returns the note for transpose mode
1033
// if -1, the stack is empty
1034
/////////////////////////////////////////////////////////////////////////////
1023 tk 1035
s32 SEQ_MIDI_IN_TransposerNoteGet(u8 bus, u8 hold)
182 tk 1036
{
1037
  if( hold )
1023 tk 1038
    return transposer_hold_note[bus];
182 tk 1039
 
1023 tk 1040
  return bus_notestack[bus][BUS_NOTESTACK_TRANSPOSER].len ? bus_notestack[bus][BUS_NOTESTACK_TRANSPOSER].note_items[0].note : -1;
182 tk 1041
}
1042
 
1043
/////////////////////////////////////////////////////////////////////////////
1044
// Returns the note for arp mode, expected key_num range: 0..3
1045
// if -1, the stack is empty
1046
// if bit 7 is set, the last key of the stack has been played
1047
/////////////////////////////////////////////////////////////////////////////
1023 tk 1048
s32 SEQ_MIDI_IN_ArpNoteGet(u8 bus, u8 hold, u8 sorted, u8 key_num)
182 tk 1049
{
683 tk 1050
  notestack_item_t *note_ptr;
182 tk 1051
 
1052
  if( sorted )
1023 tk 1053
    note_ptr = hold ? arp_sorted_hold[bus] : bus_notestack[bus][BUS_NOTESTACK_ARP_SORTED].note_items;
182 tk 1054
  else
1023 tk 1055
    note_ptr = hold ? arp_unsorted_hold[bus] : bus_notestack[bus][BUS_NOTESTACK_ARP_UNSORTED].note_items;
182 tk 1056
 
1057
  // arp note selection is based on following algorithm:
1058
  // 1 note is played, return
1059
  //    1: first note  (#0)
1060
  //    2: first note  (#0)
1061
  //    3: first note  (#0)
1062
  //    4: first note  (#0)
1063
 
1064
  // 2 notes are played, return
1065
  //    1: first note  (#0)
1066
  //    2: second note (#1)
1067
  //    3: first note  (#0)
1068
  //    4: second note (#1)
1069
 
1070
  // 3 notes are played, return
1071
  //    1: first note  (#0)
1072
  //    2: second note (#1)
1073
  //    3: third note  (#2)
1074
  //    4: first note  (#0)
1075
 
1076
  // 4 notes are played, return
1077
  //    1: first note  (#0)
1078
  //    2: second note (#1)
1079
  //    3: third note  (#2)
1080
  //    4: fourth note (#3)
1081
 
1082
  // (stack size is identical for sorted/unsorted)
1083
  u8 num_notes;
1084
  if( hold ) {
1085
    for(num_notes=0; num_notes<4; ++num_notes)
683 tk 1086
      if( !note_ptr[num_notes].note )
182 tk 1087
    break;
1088
  } else
1023 tk 1089
    num_notes = bus_notestack[bus][BUS_NOTESTACK_ARP_SORTED].len;
182 tk 1090
 
1091
  // btw.: compare with lines of code in PIC based solution! :)
683 tk 1092
  return note_ptr[key_num % num_notes].note | ((!num_notes || key_num >= (num_notes-1)) ? 0x80 : 0);
182 tk 1093
}