Subversion Repositories svn.mios

Rev

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

Rev Author Line No. Line
465 this 1
/*
2
 * MIDI-Box Channel-Mapper
3
 *
4
 * ==========================================================================
5
 *
6
 *  Copyright (C) 2008  Matthias M├Ąchler (maechler@mm-computing.ch)
7
 *  Licensed for personal non-commercial use only.
8
 *  All other rights reserved.
9
 *
10
 * ==========================================================================
11
 */
12
 
13
 
14
/////////////////////////////////////////////////////////////////////////////
15
// Include files
16
/////////////////////////////////////////////////////////////////////////////
17
 
18
#include <cmios.h>
19
#include <pic18fregs.h>
20
 
21
 
22
/////////////////////////////////////////////////////////////////////////////
23
// Application specific 
24
/////////////////////////////////////////////////////////////////////////////
25
 
26
//each set bit of inputs/outputs assigns an channel to the bus (lsb = channel 0, msb = channel 16)
27
struct midi_bus{
780 this 28
  unsigned int inputs;
29
  unsigned int outputs;  
1201 this 30
};
780 this 31
 
465 this 32
//--constants--
33
 
499 this 34
//--1 tick = 10ms; 100 ticks == 1 sec--
465 this 35
//time that the user has to hold the preset/bus button down to init all presets/all buses
499 this 36
#define init_request_ticks 300
465 this 37
 
471 this 38
 
465 this 39
const unsigned int int_bit_ormask[16] = {
780 this 40
  0x0001,0x0002,0x0004,0x0008,  
41
  0x0010,0x0020,0x0040,0x0080,  
42
  0x0100,0x0200,0x0400,0x0800,  
43
  0x1000,0x2000,0x4000,0x8000  
1201 this 44
};
780 this 45
 
471 this 46
 
47
 
465 this 48
//--current state--
49
unsigned char current_screen_num=0;//0:prs;1:bus;2:in;3:out;stored at 0x00 in EEPROM
50
unsigned char current_preset_num=0;//stored at 0x01 of EEPROM
51
unsigned char current_bus_num=0;//stored at 0x02 of EEPROM
499 this 52
unsigned char current_shift_state=0;
465 this 53
 
507 this 54
//holds last pushed value button. will be reset on any button change.
55
//used for info screens
56
unsigned char temp_value = 0xff;
57
 
499 this 58
//--timed functions: 1: request init; 2:LED flash
59
unsigned char timed_function=0;
60
unsigned int timer_ticks_count=0;
61
 
62
//--LED flash--
63
unsigned char led_flash_led=0;
64
unsigned char led_flash_count=0;
65
unsigned char led_flash_ticks=0;
66
 
465 this 67
struct midi_bus current_preset[16];//stored in Bank Stick after change
68
signed char midi_inout_map[16][16];//map the input-> output relations for faster msg forwarding
69
 
471 this 70
 
465 this 71
//------------------------------------------
72
//----------application functions-----------
73
//------------------------------------------
74
 
499 this 75
void preset_load(unsigned char) __wparam;
76
void preset_store(unsigned char) __wparam;
77
void current_screen_set(unsigned char) __wparam;
78
void current_bus_set(unsigned char) __wparam;
79
void current_preset_set(unsigned char) __wparam;
80
void inout_map_build(void) __wparam;
81
void screen_print(void) __wparam;
507 this 82
void info_screen_print(unsigned char) __wparam;
499 this 83
void timed_function_start(unsigned char) __wparam;
84
void timed_function_stop(void) __wparam;
85
void led_flash_start(unsigned char,unsigned char,unsigned char) __wparam;
86
void led_flash_set(unsigned char) __wparam;
87
 
88
 
89
void Init(void) __wparam{
1201 this 90
  MIOS_SRIO_UpdateFrqSet(3); // ms
91
  MIOS_SRIO_NumberSet(3);//need 20 inputs / outputs 
92
  MIOS_SRIO_DebounceSet(20);
93
  MIOS_BANKSTICK_CtrlSet(0x40);//stick 0, verify disabled
94
  //load last application state
95
  current_screen_num = MIOS_EEPROM_Read(0x00);
96
  current_preset_num = MIOS_EEPROM_Read(0x01);
97
  current_bus_num = MIOS_EEPROM_Read(0x02);
98
  preset_load(current_preset_num);
99
  //init screen
100
  screen_print();
101
}
499 this 102
 
103
 
104
//---------------preset load/store/build map/init------------
105
 
106
void preset_load(unsigned char num) __wparam{
780 this 107
  unsigned int addr=num;
108
  addr <<=6;
109
  MIOS_BANKSTICK_ReadPage(addr,(char*)current_preset);
1201 this 110
}
499 this 111
 
112
 
113
void preset_store(unsigned char num) __wparam{
780 this 114
  unsigned int addr=num;
115
  addr <<=6;
116
  MIOS_BANKSTICK_WritePage(addr,(char*)current_preset);  
1201 this 117
}
780 this 118
 
499 this 119
void preset_init(unsigned char empty) __wparam{
780 this 120
  unsigned char i;
121
  for(i=0;i<16;i++){
122
    current_preset[i].inputs = current_preset[i].outputs = (empty ? 0 : int_bit_ormask[i]);
123
    midi_inout_map[i][0]= (empty ? 0xff : i);
124
    midi_inout_map[i][1]=0xff;//terminate    
125
  }
1201 this 126
}
780 this 127
 
499 this 128
void inout_map_build(void) __wparam{
780 this 129
  unsigned char input,output,bus,i;
130
  unsigned int outputs[16];
131
  for(input=0;input<16;input++)
132
    outputs[input] = 0;
133
  for(input=0;input<16;input++){
134
    for(bus=0;bus<16;bus++){
135
      for(input=0;input<16;input++){
1201 this 136
        if(current_preset[bus].inputs & int_bit_ormask[input]){
780 this 137
          outputs[input] |= current_preset[bus].outputs;
138
        }
139
      }
140
    }
1201 this 141
  }
780 this 142
  for(input=0;input<16;input++){
143
    i=0;
1201 this 144
    for(output=0;output<16;output++){
145
      if(outputs[input]&int_bit_ormask[output]){
780 this 146
        midi_inout_map[input][i++]=output;
1201 this 147
      }
148
    }
780 this 149
    midi_inout_map[input][i] = 0xff;
150
  }
1201 this 151
}
780 this 152
 
499 this 153
//-------------screen-------------------
507 this 154
 
155
void info_screen_print(unsigned char info_screen) __wparam{
780 this 156
  unsigned int values_set = 0;
157
  unsigned char bus;
158
  switch(info_screen){
159
    case 0://buses assigned to inputs?
1201 this 160
      for(bus=0;bus<16;bus++){
161
        if(current_preset[bus].inputs && (temp_value==0xff || current_preset[bus].inputs & int_bit_ormask[temp_value])){
780 this 162
          values_set |= int_bit_ormask[bus];
1201 this 163
        }
164
      }
780 this 165
      break;
166
    case 1://buses assigned to outputs?
1201 this 167
      for(bus=0;bus<16;bus++){
168
        if(current_preset[bus].outputs && (temp_value==0xff || current_preset[bus].outputs & int_bit_ormask[temp_value])){
780 this 169
          values_set |= int_bit_ormask[bus];
1201 this 170
        }
171
      }
780 this 172
      break;
173
    case 2://inputs assigned to buses?
174
      if(temp_value==0xff){//inputs of all buses
1201 this 175
        for(bus=0;bus<16;bus++){
780 this 176
          values_set |= current_preset[bus].inputs;
177
        }
1201 this 178
      }
179
      else{//only inputs of bus [temp_value]
780 this 180
        values_set = current_preset[temp_value].inputs;
1201 this 181
      }
780 this 182
      break;
183
    case 3://inputs assigned to outputs?
1201 this 184
      for(bus=0;bus<16;bus++){
185
        if(current_preset[bus].outputs && (temp_value==0xff || current_preset[bus].outputs & int_bit_ormask[temp_value])){
780 this 186
          values_set |= current_preset[bus].inputs;
1201 this 187
        }
188
      }
780 this 189
      break;
190
    case 4://outputs assigned to buses?
191
      if(temp_value==0xff){//outputs of all buses
1201 this 192
        for(bus=0;bus<16;bus++){
780 this 193
          values_set |= current_preset[bus].outputs;
194
        }
1201 this 195
      }
196
      else{//only outputs of bus [temp_value]
780 this 197
        values_set = current_preset[temp_value].outputs;
1201 this 198
      }
780 this 199
      break;
200
    case 5://outputs assigned to inputs?
1201 this 201
      for(bus=0;bus<16;bus++){
202
        if(current_preset[bus].inputs && (temp_value==0xff || current_preset[bus].inputs & int_bit_ormask[temp_value])){
780 this 203
          values_set |= current_preset[bus].outputs;
1201 this 204
        }
205
      }
780 this 206
      break;
1201 this 207
  }
780 this 208
  MIOS_DOUT_SRSet(0x01,(unsigned char)(values_set & 0x00ff));
209
  MIOS_DOUT_SRSet(0x02,(unsigned char)((values_set >>8) & 0x00ff));
1201 this 210
}
780 this 211
 
499 this 212
void screen_print(void) __wparam{
780 this 213
  if(timed_function==2)
214
    return;//no screen print on LED flash
215
  //set bitmask for screen button
216
  MIOS_DOUT_SRSet(0x00,MIOS_HLP_GetBitORMask(current_screen_num));
217
  //clear value screen
218
  MIOS_DOUT_SRSet(0x01,0x00);
219
  MIOS_DOUT_SRSet(0x02,0x00);
220
  switch(current_screen_num){
221
    case 0://preset screen
222
      if(current_preset_num < 8)      
223
        MIOS_DOUT_SRSet(0x01,MIOS_HLP_GetBitORMask(current_preset_num));
224
      else
225
        MIOS_DOUT_SRSet(0x02,MIOS_HLP_GetBitORMask(current_preset_num-8));        
226
      break;
227
    case 1://bus screen
228
      if(current_shift_state == 0x06)//buses assigned to inputs (info screen)
229
        info_screen_print(0);
230
      else if(current_shift_state == 0x0A)//buses assigned to outputs (info screen)
231
        info_screen_print(1);
232
      else{//regular bus screen
233
        if(current_bus_num < 8)      
234
          MIOS_DOUT_SRSet(0x01,MIOS_HLP_GetBitORMask(current_bus_num));
235
        else
236
          MIOS_DOUT_SRSet(0x02,MIOS_HLP_GetBitORMask(current_bus_num-8));              
1201 this 237
      }
780 this 238
      break;
239
    case 2://inputs screen
240
      if(current_shift_state == 0x06)//inputs assigned to bus (info screen)
241
        info_screen_print(2);
242
      else if(current_shift_state == 0x0C)//inputs assigned to outputs (info screen)
243
        info_screen_print(3);
244
      else{//regular input screen
245
        MIOS_DOUT_SRSet(0x01,(unsigned char)(current_preset[current_bus_num].inputs & 0x00ff));
246
        MIOS_DOUT_SRSet(0x02,(unsigned char)((current_preset[current_bus_num].inputs >>8) & 0x00ff));
1201 this 247
      }
780 this 248
      break;
249
    case 3://outputs screen
250
      if(current_shift_state == 0x0A)//outputs assigned to bus (info screen)
251
        info_screen_print(4);
252
      else if(current_shift_state == 0x0C)//outputs assigned to inputs (info screen)
253
        info_screen_print(5);
254
      else{//regular output screen
255
        MIOS_DOUT_SRSet(0x01,(unsigned char)(current_preset[current_bus_num].outputs & 0x00ff));
256
        MIOS_DOUT_SRSet(0x02,(unsigned char)((current_preset[current_bus_num].outputs >>8) & 0x00ff));
1201 this 257
      }
258
      break;
780 this 259
  }
1201 this 260
}
780 this 261
 
499 this 262
void current_screen_set(unsigned char value) __wparam{
780 this 263
  current_screen_num = value;
264
  MIOS_EEPROM_Write(0x00, current_screen_num);    
1201 this 265
}
780 this 266
 
499 this 267
void current_bus_set(unsigned char value) __wparam{
780 this 268
  current_bus_num = value;
269
  MIOS_EEPROM_Write(0x02,value);
1201 this 270
}
780 this 271
 
499 this 272
void current_preset_set(unsigned char value) __wparam{
780 this 273
  current_preset_num = value;
274
  preset_load(value);
275
  inout_map_build();
276
  MIOS_EEPROM_Write(0x01,value);
1201 this 277
}
465 this 278
 
780 this 279
 
499 this 280
//----------timed functions----------------
281
 
282
void Timer(void) __wparam{
780 this 283
  timer_ticks_count++;
1201 this 284
}
499 this 285
 
286
 
287
void timed_function_start(unsigned char func) __wparam{
780 this 288
  timer_ticks_count=0;
289
  timed_function = func;
290
  MIOS_TIMER_Init(0x01,50000);
1201 this 291
}
780 this 292
 
499 this 293
void timed_function_stop(void) __wparam{
780 this 294
  MIOS_TIMER_Stop();
295
  timed_function = 0;
296
  timer_ticks_count = 0;
1201 this 297
}
780 this 298
 
499 this 299
void led_flash_start(unsigned char led,unsigned char times,unsigned char ticks) __wparam{
780 this 300
  led_flash_led = led;
301
  led_flash_ticks = ticks;
302
  led_flash_count = (times<<1) + 1;
303
  led_flash_set(0);
304
  timed_function_start(2);
1201 this 305
}
780 this 306
 
499 this 307
void led_flash_set(unsigned char state) __wparam{
780 this 308
  if(led_flash_led == 0xff){
309
    state = (state ? 0xff : 0x00);
310
    MIOS_DOUT_SRSet(0x01,state);
311
    MIOS_DOUT_SRSet(0x02,state);
1201 this 312
  }
313
  else{
780 this 314
    MIOS_DOUT_PinSet(led_flash_led,state);
315
  }
1201 this 316
}
465 this 317
 
318
 
499 this 319
void Tick(void) __wparam{
780 this 320
  unsigned char i;
321
  if(!timed_function)
322
    return;
323
  if(timed_function==1 && (timer_ticks_count >= init_request_ticks)){
324
    timed_function_stop();
325
    if(!current_screen_num){//screen is preset
326
      preset_init(0);
327
      preset_store(0);
328
      preset_init(1);
1201 this 329
      for(i=1;i<16;i++){
780 this 330
        preset_store(i);
1201 this 331
      }
780 this 332
      current_preset_set(0);
333
      current_bus_set(0);
334
      inout_map_build();
335
      led_flash_start(0xff,5,10);//flash 5 times
1201 this 336
    }
780 this 337
    else{//screen is bank
338
      preset_init(1);//empty current preset
339
      current_bus_set(0);
340
      led_flash_start(0xff,2,10);//flash 2 times
341
    }
1201 this 342
  }
780 this 343
  else if(timed_function==2 && (timer_ticks_count >= led_flash_ticks)){
344
    if(led_flash_count > 1){
345
      led_flash_set(led_flash_count-- & 0x01);
346
      timer_ticks_count = 0;
1201 this 347
    }
780 this 348
    else{
349
      timed_function_stop();
350
      screen_print();
351
    }
352
  }
1201 this 353
}
465 this 354
 
780 this 355
 
499 this 356
//------------------button handling-----------------------
465 this 357
 
499 this 358
void DIN_NotifyToggle(unsigned char pin, unsigned char pin_value) __wparam{
780 this 359
  unsigned char i,chn_out,chn_in;
360
  if(timed_function==1)
361
    timed_function_stop();//stop clear request on every button change
362
  else if(timed_function==2 && !pin_value)
363
    return;//button push will only be processed when no LED's are flashing.
364
  if(pin > 7 && !pin_value){//this is a temp_value button. only handle if button is pushed
365
    temp_value = pin - 8;
366
    if((current_shift_state & -current_shift_state) == current_shift_state){//max. one screen button pushed, one bit set
1201 this 367
      switch(current_screen_num){
368
        case 0://preset screen
369
          if (current_shift_state & MIOS_HLP_GetBitORMask(0)){
370
            preset_store(current_preset_num);
371
            led_flash_start(current_preset_num+8,0,50);//LED off for half a second to indicate save
780 this 372
          }
1201 this 373
          else{
374
            current_preset_set(temp_value);
375
          }
376
          break;      
377
        case 1://bus screen
378
          current_bus_set(temp_value);
379
          break;      
380
        case 2://input screen
381
          if (current_shift_state & MIOS_HLP_GetBitORMask(2)){//add/remove input chanel
382
            current_preset[current_bus_num].inputs =
383
              (current_preset[current_bus_num].inputs & int_bit_ormask[temp_value])?
384
                (current_preset[current_bus_num].inputs ^ int_bit_ormask[temp_value]):
385
                (current_preset[current_bus_num].inputs | int_bit_ormask[temp_value]);
386
          }
387
          else{//set / unset input channel
388
            current_preset[current_bus_num].inputs =
389
              (current_preset[current_bus_num].inputs==int_bit_ormask[temp_value]) ? 0x0000 :int_bit_ormask[temp_value];
390
          }    
391
          inout_map_build();
392
          break;      
393
        case 3://output screen
394
          if (current_shift_state & MIOS_HLP_GetBitORMask(3)){//set/unset output chanel
395
            current_preset[current_bus_num].outputs =
396
              (current_preset[current_bus_num].outputs & int_bit_ormask[temp_value])?
397
                (current_preset[current_bus_num].outputs ^ int_bit_ormask[temp_value]):
398
                (current_preset[current_bus_num].outputs | int_bit_ormask[temp_value]);
399
          }
400
          else{//add/remove output chanel
401
            current_preset[current_bus_num].outputs =
402
              (current_preset[current_bus_num].outputs==int_bit_ormask[temp_value]) ?
403
                0x0000 :int_bit_ormask[temp_value];
404
          }        
405
          inout_map_build();
406
          break;
407
      }
780 this 408
    }
1201 this 409
  }
780 this 410
  else if(pin < 4){
411
    temp_value = 0xff;
1201 this 412
    if(pin_value){
780 this 413
      current_shift_state &= ~MIOS_HLP_GetBitORMask(pin);//remove shift flag
1201 this 414
    }
780 this 415
    else{
416
      if(!current_shift_state){
417
        current_screen_set(pin);
418
        if(pin < 2)//start init request countdown
419
          timed_function_start(1);
1201 this 420
      }
780 this 421
      current_shift_state |= MIOS_HLP_GetBitORMask(pin);//add shift flag
422
    }
1201 this 423
  }
780 this 424
  screen_print();
1201 this 425
}
780 this 426
 
499 this 427
 
428
 
429
//----------------MIDI Bytes / Events receive-------------------------------
430
 
431
//this function forwards all system messages to the output
465 this 432
void MPROC_NotifyReceivedByte(unsigned char byte) __wparam{
780 this 433
  static unsigned char fx_status = 0;
434
  if(byte >= 0xf0){//system status byte
435
    MIOS_MIDI_TxBufferPut(byte);
436
     //determine status
437
    switch(byte){
438
      case 0xf1://midi timecode 
439
      case 0xf3://songselect
440
        fx_status = 1;
441
        break;  
442
      case 0xf2://songposition pointer
443
        fx_status = 2;        
444
        break;
445
      case 0xf0://sysex, forward until 0xf7
446
        fx_status = 0xff;
447
        break;
448
      default://applies also on 0xf7!
449
        fx_status = 0;
1201 this 450
    }  
451
  }
452
  else if(fx_status){
453
    MIOS_MIDI_TxBufferPut(byte);
454
    if(fx_status!=0xff){
455
      fx_status--;
456
    }
457
  }
458
}
465 this 459
 
499 this 460
 
465 this 461
void MPROC_NotifyReceivedEvnt(unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam{
780 this 462
  unsigned char i;
463
  unsigned char evnt_type = evnt0 & 0xf0;
464
  unsigned char in_chn = evnt0 & 0x0f;
465
  unsigned char evnt2_send = !(evnt_type == 0xc0 || evnt_type == 0xd0);
466
  for(i=0;i<16 && midi_inout_map[in_chn][i]!=-1;i++){
467
    MIOS_MIDI_TxBufferPut(evnt_type+midi_inout_map[in_chn][i]);
468
    MIOS_MIDI_TxBufferPut(evnt1);
1201 this 469
    if(evnt2_send){
780 this 470
      MIOS_MIDI_TxBufferPut(evnt2);
471
    }
472
  }
1201 this 473
}
465 this 474
 
475
 
499 this 476
 
477
 
478
//---------------------------not used in this application----------------
479
 
465 this 480
void DISPLAY_Init(void) __wparam{
1201 this 481
}
465 this 482
 
483
void DISPLAY_Tick(void) __wparam{
1201 this 484
}
499 this 485
 
465 this 486
void MPROC_NotifyFoundEvent(unsigned entry, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam{
1201 this 487
}
465 this 488
 
489
void MPROC_NotifyTimeout(void) __wparam{
1201 this 490
}
465 this 491
 
492
void SR_Service_Prepare(void) __wparam{
1201 this 493
}
465 this 494
 
495
void SR_Service_Finish(void) __wparam{
1201 this 496
}
465 this 497
 
498
void ENC_NotifyChange(unsigned char encoder, char incrementer) __wparam{
1201 this 499
}
465 this 500
 
501
void AIN_NotifyChange(unsigned char pin, unsigned int pin_value) __wparam{
1201 this 502
}