Subversion Repositories svn.mios

Rev

Rev 1201 | 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);
1202 this 110
  inout_map_build();
1201 this 111
}
499 this 112
 
113
 
114
void preset_store(unsigned char num) __wparam{
780 this 115
  unsigned int addr=num;
116
  addr <<=6;
117
  MIOS_BANKSTICK_WritePage(addr,(char*)current_preset);  
1201 this 118
}
780 this 119
 
499 this 120
void preset_init(unsigned char empty) __wparam{
780 this 121
  unsigned char i;
122
  for(i=0;i<16;i++){
123
    current_preset[i].inputs = current_preset[i].outputs = (empty ? 0 : int_bit_ormask[i]);
124
    midi_inout_map[i][0]= (empty ? 0xff : i);
125
    midi_inout_map[i][1]=0xff;//terminate    
126
  }
1201 this 127
}
780 this 128
 
499 this 129
void inout_map_build(void) __wparam{
780 this 130
  unsigned char input,output,bus,i;
131
  unsigned int outputs[16];
132
  for(input=0;input<16;input++)
133
    outputs[input] = 0;
134
  for(input=0;input<16;input++){
135
    for(bus=0;bus<16;bus++){
136
      for(input=0;input<16;input++){
1201 this 137
        if(current_preset[bus].inputs & int_bit_ormask[input]){
780 this 138
          outputs[input] |= current_preset[bus].outputs;
139
        }
140
      }
141
    }
1201 this 142
  }
780 this 143
  for(input=0;input<16;input++){
144
    i=0;
1201 this 145
    for(output=0;output<16;output++){
146
      if(outputs[input]&int_bit_ormask[output]){
780 this 147
        midi_inout_map[input][i++]=output;
1201 this 148
      }
149
    }
780 this 150
    midi_inout_map[input][i] = 0xff;
151
  }
1201 this 152
}
780 this 153
 
499 this 154
//-------------screen-------------------
507 this 155
 
156
void info_screen_print(unsigned char info_screen) __wparam{
780 this 157
  unsigned int values_set = 0;
158
  unsigned char bus;
159
  switch(info_screen){
160
    case 0://buses assigned to inputs?
1201 this 161
      for(bus=0;bus<16;bus++){
162
        if(current_preset[bus].inputs && (temp_value==0xff || current_preset[bus].inputs & int_bit_ormask[temp_value])){
780 this 163
          values_set |= int_bit_ormask[bus];
1201 this 164
        }
165
      }
780 this 166
      break;
167
    case 1://buses assigned to outputs?
1201 this 168
      for(bus=0;bus<16;bus++){
169
        if(current_preset[bus].outputs && (temp_value==0xff || current_preset[bus].outputs & int_bit_ormask[temp_value])){
780 this 170
          values_set |= int_bit_ormask[bus];
1201 this 171
        }
172
      }
780 this 173
      break;
174
    case 2://inputs assigned to buses?
175
      if(temp_value==0xff){//inputs of all buses
1201 this 176
        for(bus=0;bus<16;bus++){
780 this 177
          values_set |= current_preset[bus].inputs;
178
        }
1201 this 179
      }
180
      else{//only inputs of bus [temp_value]
780 this 181
        values_set = current_preset[temp_value].inputs;
1201 this 182
      }
780 this 183
      break;
184
    case 3://inputs assigned to outputs?
1201 this 185
      for(bus=0;bus<16;bus++){
186
        if(current_preset[bus].outputs && (temp_value==0xff || current_preset[bus].outputs & int_bit_ormask[temp_value])){
780 this 187
          values_set |= current_preset[bus].inputs;
1201 this 188
        }
189
      }
780 this 190
      break;
191
    case 4://outputs assigned to buses?
192
      if(temp_value==0xff){//outputs of all buses
1201 this 193
        for(bus=0;bus<16;bus++){
780 this 194
          values_set |= current_preset[bus].outputs;
195
        }
1201 this 196
      }
197
      else{//only outputs of bus [temp_value]
780 this 198
        values_set = current_preset[temp_value].outputs;
1201 this 199
      }
780 this 200
      break;
201
    case 5://outputs assigned to inputs?
1201 this 202
      for(bus=0;bus<16;bus++){
203
        if(current_preset[bus].inputs && (temp_value==0xff || current_preset[bus].inputs & int_bit_ormask[temp_value])){
780 this 204
          values_set |= current_preset[bus].outputs;
1201 this 205
        }
206
      }
780 this 207
      break;
1201 this 208
  }
780 this 209
  MIOS_DOUT_SRSet(0x01,(unsigned char)(values_set & 0x00ff));
210
  MIOS_DOUT_SRSet(0x02,(unsigned char)((values_set >>8) & 0x00ff));
1201 this 211
}
780 this 212
 
499 this 213
void screen_print(void) __wparam{
780 this 214
  if(timed_function==2)
215
    return;//no screen print on LED flash
216
  //set bitmask for screen button
217
  MIOS_DOUT_SRSet(0x00,MIOS_HLP_GetBitORMask(current_screen_num));
218
  //clear value screen
219
  MIOS_DOUT_SRSet(0x01,0x00);
220
  MIOS_DOUT_SRSet(0x02,0x00);
221
  switch(current_screen_num){
222
    case 0://preset screen
223
      if(current_preset_num < 8)      
224
        MIOS_DOUT_SRSet(0x01,MIOS_HLP_GetBitORMask(current_preset_num));
225
      else
226
        MIOS_DOUT_SRSet(0x02,MIOS_HLP_GetBitORMask(current_preset_num-8));        
227
      break;
228
    case 1://bus screen
229
      if(current_shift_state == 0x06)//buses assigned to inputs (info screen)
230
        info_screen_print(0);
231
      else if(current_shift_state == 0x0A)//buses assigned to outputs (info screen)
232
        info_screen_print(1);
233
      else{//regular bus screen
234
        if(current_bus_num < 8)      
235
          MIOS_DOUT_SRSet(0x01,MIOS_HLP_GetBitORMask(current_bus_num));
236
        else
237
          MIOS_DOUT_SRSet(0x02,MIOS_HLP_GetBitORMask(current_bus_num-8));              
1201 this 238
      }
780 this 239
      break;
240
    case 2://inputs screen
241
      if(current_shift_state == 0x06)//inputs assigned to bus (info screen)
242
        info_screen_print(2);
243
      else if(current_shift_state == 0x0C)//inputs assigned to outputs (info screen)
244
        info_screen_print(3);
245
      else{//regular input screen
246
        MIOS_DOUT_SRSet(0x01,(unsigned char)(current_preset[current_bus_num].inputs & 0x00ff));
247
        MIOS_DOUT_SRSet(0x02,(unsigned char)((current_preset[current_bus_num].inputs >>8) & 0x00ff));
1201 this 248
      }
780 this 249
      break;
250
    case 3://outputs screen
251
      if(current_shift_state == 0x0A)//outputs assigned to bus (info screen)
252
        info_screen_print(4);
253
      else if(current_shift_state == 0x0C)//outputs assigned to inputs (info screen)
254
        info_screen_print(5);
255
      else{//regular output screen
256
        MIOS_DOUT_SRSet(0x01,(unsigned char)(current_preset[current_bus_num].outputs & 0x00ff));
257
        MIOS_DOUT_SRSet(0x02,(unsigned char)((current_preset[current_bus_num].outputs >>8) & 0x00ff));
1201 this 258
      }
259
      break;
780 this 260
  }
1201 this 261
}
780 this 262
 
499 this 263
void current_screen_set(unsigned char value) __wparam{
780 this 264
  current_screen_num = value;
265
  MIOS_EEPROM_Write(0x00, current_screen_num);    
1201 this 266
}
780 this 267
 
499 this 268
void current_bus_set(unsigned char value) __wparam{
780 this 269
  current_bus_num = value;
270
  MIOS_EEPROM_Write(0x02,value);
1201 this 271
}
780 this 272
 
499 this 273
void current_preset_set(unsigned char value) __wparam{
780 this 274
  current_preset_num = value;
275
  preset_load(value);
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
      led_flash_start(0xff,5,10);//flash 5 times
1201 this 335
    }
780 this 336
    else{//screen is bank
337
      preset_init(1);//empty current preset
338
      current_bus_set(0);
339
      led_flash_start(0xff,2,10);//flash 2 times
340
    }
1201 this 341
  }
780 this 342
  else if(timed_function==2 && (timer_ticks_count >= led_flash_ticks)){
343
    if(led_flash_count > 1){
344
      led_flash_set(led_flash_count-- & 0x01);
345
      timer_ticks_count = 0;
1201 this 346
    }
780 this 347
    else{
348
      timed_function_stop();
349
      screen_print();
350
    }
351
  }
1201 this 352
}
465 this 353
 
780 this 354
 
499 this 355
//------------------button handling-----------------------
465 this 356
 
499 this 357
void DIN_NotifyToggle(unsigned char pin, unsigned char pin_value) __wparam{
780 this 358
  unsigned char i,chn_out,chn_in;
359
  if(timed_function==1)
360
    timed_function_stop();//stop clear request on every button change
361
  else if(timed_function==2 && !pin_value)
362
    return;//button push will only be processed when no LED's are flashing.
363
  if(pin > 7 && !pin_value){//this is a temp_value button. only handle if button is pushed
364
    temp_value = pin - 8;
365
    if((current_shift_state & -current_shift_state) == current_shift_state){//max. one screen button pushed, one bit set
1201 this 366
      switch(current_screen_num){
367
        case 0://preset screen
368
          if (current_shift_state & MIOS_HLP_GetBitORMask(0)){
369
            preset_store(current_preset_num);
370
            led_flash_start(current_preset_num+8,0,50);//LED off for half a second to indicate save
780 this 371
          }
1201 this 372
          else{
373
            current_preset_set(temp_value);
374
          }
375
          break;      
376
        case 1://bus screen
377
          current_bus_set(temp_value);
378
          break;      
379
        case 2://input screen
380
          if (current_shift_state & MIOS_HLP_GetBitORMask(2)){//add/remove input chanel
381
            current_preset[current_bus_num].inputs =
382
              (current_preset[current_bus_num].inputs & int_bit_ormask[temp_value])?
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
          }
386
          else{//set / unset input channel
387
            current_preset[current_bus_num].inputs =
388
              (current_preset[current_bus_num].inputs==int_bit_ormask[temp_value]) ? 0x0000 :int_bit_ormask[temp_value];
389
          }    
390
          inout_map_build();
391
          break;      
392
        case 3://output screen
393
          if (current_shift_state & MIOS_HLP_GetBitORMask(3)){//set/unset output chanel
394
            current_preset[current_bus_num].outputs =
395
              (current_preset[current_bus_num].outputs & int_bit_ormask[temp_value])?
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
          }
399
          else{//add/remove output chanel
400
            current_preset[current_bus_num].outputs =
401
              (current_preset[current_bus_num].outputs==int_bit_ormask[temp_value]) ?
402
                0x0000 :int_bit_ormask[temp_value];
403
          }        
404
          inout_map_build();
405
          break;
406
      }
780 this 407
    }
1201 this 408
  }
780 this 409
  else if(pin < 4){
410
    temp_value = 0xff;
1201 this 411
    if(pin_value){
780 this 412
      current_shift_state &= ~MIOS_HLP_GetBitORMask(pin);//remove shift flag
1201 this 413
    }
780 this 414
    else{
415
      if(!current_shift_state){
416
        current_screen_set(pin);
417
        if(pin < 2)//start init request countdown
418
          timed_function_start(1);
1201 this 419
      }
780 this 420
      current_shift_state |= MIOS_HLP_GetBitORMask(pin);//add shift flag
421
    }
1201 this 422
  }
780 this 423
  screen_print();
1201 this 424
}
780 this 425
 
499 this 426
 
427
 
428
//----------------MIDI Bytes / Events receive-------------------------------
429
 
430
//this function forwards all system messages to the output
465 this 431
void MPROC_NotifyReceivedByte(unsigned char byte) __wparam{
780 this 432
  static unsigned char fx_status = 0;
433
  if(byte >= 0xf0){//system status byte
434
    MIOS_MIDI_TxBufferPut(byte);
435
     //determine status
436
    switch(byte){
437
      case 0xf1://midi timecode 
438
      case 0xf3://songselect
439
        fx_status = 1;
440
        break;  
441
      case 0xf2://songposition pointer
442
        fx_status = 2;        
443
        break;
444
      case 0xf0://sysex, forward until 0xf7
445
        fx_status = 0xff;
446
        break;
447
      default://applies also on 0xf7!
448
        fx_status = 0;
1201 this 449
    }  
450
  }
451
  else if(fx_status){
452
    MIOS_MIDI_TxBufferPut(byte);
453
    if(fx_status!=0xff){
454
      fx_status--;
455
    }
456
  }
457
}
465 this 458
 
499 this 459
 
465 this 460
void MPROC_NotifyReceivedEvnt(unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam{
780 this 461
  unsigned char i;
462
  unsigned char evnt_type = evnt0 & 0xf0;
463
  unsigned char in_chn = evnt0 & 0x0f;
464
  unsigned char evnt2_send = !(evnt_type == 0xc0 || evnt_type == 0xd0);
465
  for(i=0;i<16 && midi_inout_map[in_chn][i]!=-1;i++){
466
    MIOS_MIDI_TxBufferPut(evnt_type+midi_inout_map[in_chn][i]);
467
    MIOS_MIDI_TxBufferPut(evnt1);
1201 this 468
    if(evnt2_send){
780 this 469
      MIOS_MIDI_TxBufferPut(evnt2);
470
    }
471
  }
1201 this 472
}
465 this 473
 
474
 
499 this 475
 
476
 
477
//---------------------------not used in this application----------------
478
 
465 this 479
void DISPLAY_Init(void) __wparam{
1201 this 480
}
465 this 481
 
482
void DISPLAY_Tick(void) __wparam{
1201 this 483
}
499 this 484
 
465 this 485
void MPROC_NotifyFoundEvent(unsigned entry, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam{
1201 this 486
}
465 this 487
 
488
void MPROC_NotifyTimeout(void) __wparam{
1201 this 489
}
465 this 490
 
491
void SR_Service_Prepare(void) __wparam{
1201 this 492
}
465 this 493
 
494
void SR_Service_Finish(void) __wparam{
1201 this 495
}
465 this 496
 
497
void ENC_NotifyChange(unsigned char encoder, char incrementer) __wparam{
1201 this 498
}
465 this 499
 
500
void AIN_NotifyChange(unsigned char pin, unsigned int pin_value) __wparam{
1201 this 501
}