Subversion Repositories svn.mios

Rev

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

Rev Author Line No. Line
859 tk 1
// $Id: main.c 1194 2015-06-08 21:05:14Z tk $
2
/*
3
 * MBHP_SCALAR firmware
4
 *
5
 * ==========================================================================
6
 *
7
 *  Copyright (C) 2009 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 <cmios.h>
19
#include <pic18fregs.h>
20
 
909 tk 21
#include <blm_scalar.h>
859 tk 22
#include "main.h"
910 tk 23
#include "sysex.h"
859 tk 24
 
25
 
909 tk 26
/////////////////////////////////////////////////////////////////////////////
859 tk 27
// Number of LED rows (1..16)
28
/////////////////////////////////////////////////////////////////////////////
29
 
909 tk 30
#define NUM_LED_ROWS 16
859 tk 31
 
32
 
33
/////////////////////////////////////////////////////////////////////////////
34
// Global variables
35
/////////////////////////////////////////////////////////////////////////////
36
 
37
/////////////////////////////////////////////////////////////////////////////
38
// Local variables
39
/////////////////////////////////////////////////////////////////////////////
40
 
914 tk 41
// send layout informations or ping each 5 seconds
42
static unsigned int sysexRequestTimer;
43
static unsigned char midiDataReceived;
859 tk 44
 
910 tk 45
static unsigned char testmode;
46
 
47
 
1194 tk 48
#if BLM_AIN_PIN_MAP
49
// optional AIN pin map
50
static const ain_pin_map[8] = {3, 2, 1, 0, 4, 5, 6, 7};
51
#endif
52
 
53
 
859 tk 54
/////////////////////////////////////////////////////////////////////////////
55
// This function is called by MIOS after startup to initialize the 
56
// application
57
/////////////////////////////////////////////////////////////////////////////
58
void Init(void) __wparam
59
{
914 tk 60
  sysexRequestTimer = 0;
61
  midiDataReceived = 0;
910 tk 62
  testmode = 1;
63
 
859 tk 64
  // initialize the scan matrix driver
909 tk 65
  BLM_SCALAR_Init();
66
 
910 tk 67
  // initialize SysEx parser
68
  SYSEX_Init();
69
 
859 tk 70
  // initialize the shift registers
71
  MIOS_SRIO_NumberSet(16);           // use up to 16 shift registers
72
  MIOS_SRIO_UpdateFrqSet(1);         // set update frequency
910 tk 73
 
74
  // configure AIN
75
  MIOS_AIN_NumberSet(8);   // up to 8 pots connected
76
  MIOS_AIN_UnMuxed();      // no AINX4 modules are used
77
  MIOS_AIN_DeadbandSet(7); // should be 7 when 7bit resolution is used
859 tk 78
}
79
 
910 tk 80
 
81
 
859 tk 82
/////////////////////////////////////////////////////////////////////////////
914 tk 83
// This function notifies received BLM data and exits testmode
910 tk 84
/////////////////////////////////////////////////////////////////////////////
914 tk 85
static void notifyDataReceived(void)
910 tk 86
{
914 tk 87
  midiDataReceived = 1;
910 tk 88
  testmode = 0;
89
}
90
 
91
 
92
/////////////////////////////////////////////////////////////////////////////
859 tk 93
// This function is called by MIOS in the mainloop when nothing else is to do
94
/////////////////////////////////////////////////////////////////////////////
95
void Tick(void) __wparam
96
{
910 tk 97
  // send layout informations each 5 seconds if BLM hasn't been updated
914 tk 98
  if( sysexRequestTimer > 5000 ) {
99
    INTCONbits.GIE = 0;
100
    sysexRequestTimer = 0;
101
    INTCONbits.GIE = 1;
102
 
103
    if( midiDataReceived )
104
      SYSEX_SendAck(SYSEX_ACK, 0x00);
105
    else
106
      SYSEX_SendLayoutInfo();
107
 
108
    midiDataReceived = 0;
910 tk 109
  }
110
 
859 tk 111
  // call the scan matrix button handler
909 tk 112
  BLM_SCALAR_ButtonHandler();
859 tk 113
}
114
 
115
/////////////////////////////////////////////////////////////////////////////
116
// This function is periodically called by MIOS. The frequency has to be
117
// initialized with MIOS_Timer_Set
118
/////////////////////////////////////////////////////////////////////////////
119
void Timer(void) __wparam
120
{
121
}
122
 
123
/////////////////////////////////////////////////////////////////////////////
124
// This function is called by MIOS when the display content should be 
125
// initialized. Thats the case during startup and after a temporary message
126
// has been printed on the screen
127
/////////////////////////////////////////////////////////////////////////////
128
void DISPLAY_Init(void) __wparam
129
{
130
  // clear LCD
131
  MIOS_LCD_Clear();
132
 
133
  // print static screen (no real LCD support)
134
  MIOS_LCD_CursorSet(0x00 + 0);
135
  MIOS_LCD_PrintCString("MBHP_BLM_SCALAR");
136
  MIOS_LCD_CursorSet(0x40 + 0);
137
  MIOS_LCD_PrintCString("No LCD supported");
138
}
139
 
140
/////////////////////////////////////////////////////////////////////////////
141
//  This function is called in the mainloop when no temporary message is shown
142
//  on screen. Print the realtime messages here
143
/////////////////////////////////////////////////////////////////////////////
144
void DISPLAY_Tick(void) __wparam
145
{
146
}
147
 
148
/////////////////////////////////////////////////////////////////////////////
149
//  This function is called by MIOS when a complete MIDI event has been received
150
/////////////////////////////////////////////////////////////////////////////
151
void MPROC_NotifyReceivedEvnt(unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
152
{
153
  unsigned char chn = evnt0 & 0x0f;
154
  unsigned char event_type = evnt0 >> 4;
155
 
156
  if( chn >= NUM_LED_ROWS )
157
    return;
158
 
159
  // control the Duo-LEDs via Note On/Off Events
160
  // The colour is controlled with velocity value:
161
  // 0x00:       both LEDs off
162
  // 0x01..0x3f: green LED on
163
  // 0x40..0x5f: red LED on
164
  // 0x60..0x7f: both LEDs on
165
 
910 tk 166
  // MIDI event assignments: see README.txt
859 tk 167
 
910 tk 168
  if( (event_type == 0x8 || event_type == 0x9) ) {
169
    unsigned char led_row_ix = 0;
170
    unsigned char led_column_ix = 0;
171
    unsigned char modify_led = 0;
859 tk 172
 
910 tk 173
    if( evnt1 <= 0x0f ) {
174
      // BLM16x16 LEDs
175
      led_row_ix = 2*chn + (evnt1 >> 3);
176
      led_column_ix = evnt1 & 0x7;
177
      modify_led = 1;
178
    } else if( evnt1 == 0x40 ) {
179
      // extra column LEDs
180
      led_row_ix = 0x20 + ((chn & 3) << 1);
181
      led_column_ix = chn >> 2;
182
      modify_led = 1;
183
    } else if( chn == 0 && evnt1 >= 0x60 && evnt1 <= 0x6f ) {
184
      // extra row LEDs
185
      led_row_ix = 0x21 + ((evnt1 >> 1) & 6);
186
      led_column_ix = evnt1 & 3;
187
      modify_led = 1;
188
    } else if( chn == 0xf && evnt1 >= 0x60 && evnt1 <= 0x6f ) {
189
      // additional extra LEDs
190
      led_row_ix = 0x21 + ((evnt1 >> 1) & 6);
191
      led_column_ix = 4 + (evnt1 & 3);
192
      modify_led = 1;
193
    }
859 tk 194
 
195
 
910 tk 196
    if( modify_led ) {
197
      // 90 xx 00 is the same like a note off event!
198
      // (-> http://www.borg.com/~jglatt/tech/midispec.htm)
199
      if( event_type == 0x8 || evnt2 == 0x00 ) {
200
    // Note Off or velocity == 0x00: clear both LEDs
201
    blm_scalar_row_green[led_row_ix] &= MIOS_HLP_GetBitANDMask(led_column_ix);
202
    blm_scalar_row_red[led_row_ix]   &= MIOS_HLP_GetBitANDMask(led_column_ix);
859 tk 203
 
910 tk 204
      } else if( evnt2 < 0x40 ) {
205
    // Velocity < 0x40: set green LED, clear red LED
206
    blm_scalar_row_green[led_row_ix] |= MIOS_HLP_GetBitORMask(led_column_ix);
207
    blm_scalar_row_red[led_row_ix]   &= MIOS_HLP_GetBitANDMask(led_column_ix);
208
      } else if( evnt2 < 0x60 ) {
209
    // Velocity < 0x60: clear green LED, set red LED
210
    blm_scalar_row_green[led_row_ix] &= MIOS_HLP_GetBitANDMask(led_column_ix);
211
    blm_scalar_row_red[led_row_ix]   |= MIOS_HLP_GetBitORMask(led_column_ix);
212
      } else {
213
    // Velocity >= 0x60: set both LEDs
214
    blm_scalar_row_green[led_row_ix] |= MIOS_HLP_GetBitORMask(led_column_ix);
215
    blm_scalar_row_red[led_row_ix]   |= MIOS_HLP_GetBitORMask(led_column_ix);
216
      }
859 tk 217
 
914 tk 218
      notifyDataReceived();
859 tk 219
    }
220
  }
221
 
222
  // "check for packed format" which is transfered via CCs
223
  else if( event_type == 0xb ) {
224
    unsigned char pattern = evnt2;
225
    if( evnt1 & 0x01 )
226
      pattern |= (1 << 7);
227
 
228
    switch( evnt1 & 0xfe ) {
910 tk 229
      case 0x10: blm_scalar_row_green[2*chn + 0] = pattern; break;
230
      case 0x12: blm_scalar_row_green[2*chn + 1] = pattern; break;
231
 
911 tk 232
      case 0x18:
233
      case 0x1a: {
912 tk 234
    unsigned char offset = ((evnt1 & 0x02) ? 16 : 0) + (chn >> 3);
911 tk 235
    unsigned char mask = MIOS_HLP_GetBitORMask(chn);
912 tk 236
    if( pattern & 0x01 ) { blm_scalar_row_green[offset +  0] |= mask; } else { blm_scalar_row_green[offset +  0] &= ~mask; }
237
    if( pattern & 0x02 ) { blm_scalar_row_green[offset +  2] |= mask; } else { blm_scalar_row_green[offset +  2] &= ~mask; }
238
    if( pattern & 0x04 ) { blm_scalar_row_green[offset +  4] |= mask; } else { blm_scalar_row_green[offset +  4] &= ~mask; }
239
    if( pattern & 0x08 ) { blm_scalar_row_green[offset +  6] |= mask; } else { blm_scalar_row_green[offset +  6] &= ~mask; }
240
    if( pattern & 0x10 ) { blm_scalar_row_green[offset +  8] |= mask; } else { blm_scalar_row_green[offset +  8] &= ~mask; }
241
    if( pattern & 0x20 ) { blm_scalar_row_green[offset + 10] |= mask; } else { blm_scalar_row_green[offset + 10] &= ~mask; }
242
    if( pattern & 0x40 ) { blm_scalar_row_green[offset + 12] |= mask; } else { blm_scalar_row_green[offset + 12] &= ~mask; }
243
    if( pattern & 0x80 ) { blm_scalar_row_green[offset + 14] |= mask; } else { blm_scalar_row_green[offset + 14] &= ~mask; }
911 tk 244
      } break;
245
 
910 tk 246
      case 0x20: blm_scalar_row_red[2*chn + 0] = pattern; break;
247
      case 0x22: blm_scalar_row_red[2*chn + 1] = pattern; break;
248
 
911 tk 249
      case 0x28:
250
      case 0x2a: {
912 tk 251
    unsigned char offset = ((evnt1 & 0x02) ? 16 : 0) + (chn >> 3);
911 tk 252
    unsigned char mask = MIOS_HLP_GetBitORMask(chn);
912 tk 253
    if( pattern & 0x01 ) { blm_scalar_row_red[offset +  0] |= mask; } else { blm_scalar_row_red[offset +  0] &= ~mask; }
254
    if( pattern & 0x02 ) { blm_scalar_row_red[offset +  2] |= mask; } else { blm_scalar_row_red[offset +  2] &= ~mask; }
255
    if( pattern & 0x04 ) { blm_scalar_row_red[offset +  4] |= mask; } else { blm_scalar_row_red[offset +  4] &= ~mask; }
256
    if( pattern & 0x08 ) { blm_scalar_row_red[offset +  6] |= mask; } else { blm_scalar_row_red[offset +  6] &= ~mask; }
257
    if( pattern & 0x10 ) { blm_scalar_row_red[offset +  8] |= mask; } else { blm_scalar_row_red[offset +  8] &= ~mask; }
258
    if( pattern & 0x20 ) { blm_scalar_row_red[offset + 10] |= mask; } else { blm_scalar_row_red[offset + 10] &= ~mask; }
259
    if( pattern & 0x40 ) { blm_scalar_row_red[offset + 12] |= mask; } else { blm_scalar_row_red[offset + 12] &= ~mask; }
260
    if( pattern & 0x80 ) { blm_scalar_row_red[offset + 14] |= mask; } else { blm_scalar_row_red[offset + 14] &= ~mask; }
911 tk 261
      } break;
262
 
910 tk 263
      case 0x40:
264
      case 0x42: {
265
    if( chn == 0 ) {
266
      // Bit  0 -> led_row_ix 0x20, Bit 0
267
      // Bit  1 -> led_row_ix 0x22, Bit 0
268
      // Bit  2 -> led_row_ix 0x24, Bit 0
269
      // Bit  3 -> led_row_ix 0x26, Bit 0
270
      // Bit  4 -> led_row_ix 0x20, Bit 1
271
      // Bit  5 -> led_row_ix 0x22, Bit 1
272
      // Bit  6 -> led_row_ix 0x24, Bit 1
273
      // Bit  7 -> led_row_ix 0x26, Bit 1
274
      // Bit  8 -> led_row_ix 0x20, Bit 2
275
      // Bit  9 -> led_row_ix 0x22, Bit 2
276
      // Bit 10 -> led_row_ix 0x24, Bit 2
277
      // Bit 11 -> led_row_ix 0x26, Bit 2
278
      // Bit 12 -> led_row_ix 0x20, Bit 3
279
      // Bit 13 -> led_row_ix 0x22, Bit 3
280
      // Bit 14 -> led_row_ix 0x24, Bit 3
281
      // Bit 15 -> led_row_ix 0x26, Bit 3
282
      if( evnt1 >= 0x42 ) {
283
        blm_scalar_row_green[0x20] = (blm_scalar_row_green[0x20] & 0xf3) | ((pattern << 2) & 0x04) | ((pattern >> 1) & 0x08);
284
        blm_scalar_row_green[0x22] = (blm_scalar_row_green[0x22] & 0xf3) | ((pattern << 1) & 0x04) | ((pattern >> 2) & 0x08);
285
        blm_scalar_row_green[0x24] = (blm_scalar_row_green[0x24] & 0xf3) | ((pattern << 0) & 0x04) | ((pattern >> 3) & 0x08);
286
        blm_scalar_row_green[0x26] = (blm_scalar_row_green[0x26] & 0xf3) | ((pattern >> 1) & 0x04) | ((pattern >> 4) & 0x08);
287
      } else {
288
        blm_scalar_row_green[0x20] = (blm_scalar_row_green[0x20] & 0xfc) | ((pattern >> 0) & 0x01) | ((pattern >> 3) & 0x02);
289
        blm_scalar_row_green[0x22] = (blm_scalar_row_green[0x22] & 0xfc) | ((pattern >> 1) & 0x01) | ((pattern >> 4) & 0x02);
290
        blm_scalar_row_green[0x24] = (blm_scalar_row_green[0x24] & 0xfc) | ((pattern >> 2) & 0x01) | ((pattern >> 5) & 0x02);
291
        blm_scalar_row_green[0x26] = (blm_scalar_row_green[0x26] & 0xfc) | ((pattern >> 3) & 0x01) | ((pattern >> 6) & 0x02);
292
      }
293
    }
294
      } break;
295
 
296
      case 0x48:
297
      case 0x4a: {
298
    if( chn == 0 ) {
299
      if( evnt1 >= 0x4a ) {
300
        blm_scalar_row_red[0x20] = (blm_scalar_row_red[0x20] & 0xf3) | ((pattern << 2) & 0x04) | ((pattern >> 1) & 0x08);
301
        blm_scalar_row_red[0x22] = (blm_scalar_row_red[0x22] & 0xf3) | ((pattern << 1) & 0x04) | ((pattern >> 2) & 0x08);
302
        blm_scalar_row_red[0x24] = (blm_scalar_row_red[0x24] & 0xf3) | ((pattern << 0) & 0x04) | ((pattern >> 3) & 0x08);
303
        blm_scalar_row_red[0x26] = (blm_scalar_row_red[0x26] & 0xf3) | ((pattern >> 1) & 0x04) | ((pattern >> 4) & 0x08);
304
      } else {
305
        blm_scalar_row_red[0x20] = (blm_scalar_row_red[0x20] & 0xfc) | ((pattern >> 0) & 0x01) | ((pattern >> 3) & 0x02);
306
        blm_scalar_row_red[0x22] = (blm_scalar_row_red[0x22] & 0xfc) | ((pattern >> 1) & 0x01) | ((pattern >> 4) & 0x02);
307
        blm_scalar_row_red[0x24] = (blm_scalar_row_red[0x24] & 0xfc) | ((pattern >> 2) & 0x01) | ((pattern >> 5) & 0x02);
308
        blm_scalar_row_red[0x26] = (blm_scalar_row_red[0x26] & 0xfc) | ((pattern >> 3) & 0x01) | ((pattern >> 6) & 0x02);
309
      }
310
    }
311
      } break;
312
 
313
 
314
      case 0x60:
315
      case 0x62: {
316
    unsigned char led_row_ix = (evnt1 >= 0x62) ? 0x25 : 0x21;
317
    if( chn == 0 ) {
318
      blm_scalar_row_green[led_row_ix] = (blm_scalar_row_green[led_row_ix] & 0xf0) | (pattern & 0x0f);
319
      led_row_ix += 2;
320
      blm_scalar_row_green[led_row_ix] = (blm_scalar_row_green[led_row_ix] & 0xf0) | (pattern >> 4);
321
    } else if( chn == 15 ) {
322
      blm_scalar_row_green[led_row_ix] = (blm_scalar_row_green[led_row_ix] & 0x0f) | (pattern << 4);
323
      led_row_ix += 2;
324
      blm_scalar_row_green[led_row_ix] = (blm_scalar_row_green[led_row_ix] & 0x0f) | (pattern & 0xf0);
325
    }
326
      } break;
327
 
328
      case 0x68:
329
      case 0x6a: {
330
    unsigned char led_row_ix = (evnt1 >= 0x6a) ? 0x25 : 0x21;
331
    if( chn == 0 ) {
332
      blm_scalar_row_red[led_row_ix] = (blm_scalar_row_red[led_row_ix] & 0xf0) | (pattern & 0x0f);
333
      led_row_ix += 2;
334
      blm_scalar_row_red[led_row_ix] = (blm_scalar_row_red[led_row_ix] & 0xf0) | (pattern >> 4);
335
    } else if( chn == 15 ) {
336
      blm_scalar_row_red[led_row_ix] = (blm_scalar_row_red[led_row_ix] & 0x0f) | (pattern << 4);
337
      led_row_ix += 2;
338
      blm_scalar_row_red[led_row_ix] = (blm_scalar_row_red[led_row_ix] & 0x0f) | (pattern & 0xf0);
339
    }
340
      } break;
859 tk 341
    }
910 tk 342
 
914 tk 343
    notifyDataReceived();
859 tk 344
  }
345
}
346
 
347
/////////////////////////////////////////////////////////////////////////////
348
// This function is called by MIOS when a MIDI event has been received
349
// which has been specified in the MIOS_MPROC_EVENT_TABLE
350
/////////////////////////////////////////////////////////////////////////////
351
void MPROC_NotifyFoundEvent(unsigned entry, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
352
{
353
}
354
 
355
/////////////////////////////////////////////////////////////////////////////
356
// This function is called by MIOS when a MIDI event has not been completly
357
// received within 2 seconds
358
/////////////////////////////////////////////////////////////////////////////
359
void MPROC_NotifyTimeout(void) __wparam
360
{
361
}
362
 
363
/////////////////////////////////////////////////////////////////////////////
364
// This function is called by MIOS when a MIDI byte has been received
365
/////////////////////////////////////////////////////////////////////////////
366
void MPROC_NotifyReceivedByte(unsigned char byte) __wparam
367
{
910 tk 368
  // forward byte to SysEx Parser
369
  SYSEX_Parser(byte);
859 tk 370
}
371
 
372
/////////////////////////////////////////////////////////////////////////////
373
// This function is called by MIOS before the shift register are loaded
374
/////////////////////////////////////////////////////////////////////////////
375
void SR_Service_Prepare(void) __wparam
376
{
377
  // call the Scan Matrix Driver
909 tk 378
  BLM_SCALAR_PrepareCol();
859 tk 379
}
380
 
381
/////////////////////////////////////////////////////////////////////////////
382
// This function is called by MIOS after the shift register have been loaded
383
/////////////////////////////////////////////////////////////////////////////
384
void SR_Service_Finish(void) __wparam
385
{
386
  // call the Scan Matrix Driver
909 tk 387
  BLM_SCALAR_GetRow();
910 tk 388
 
914 tk 389
  // increment request timer counter
390
  ++sysexRequestTimer;
859 tk 391
}
392
 
393
/////////////////////////////////////////////////////////////////////////////
394
// This function is called by MIOS when an button has been toggled
395
// pin_value is 1 when button released, and 0 when button pressed
396
/////////////////////////////////////////////////////////////////////////////
397
void DIN_NotifyToggle(unsigned char pin, unsigned char pin_value) __wparam
398
{
399
}
400
 
401
/////////////////////////////////////////////////////////////////////////////
402
// This function is called by MIOS when an encoder has been moved
403
// incrementer is positive when encoder has been turned clockwise, else
404
// it is negative
405
/////////////////////////////////////////////////////////////////////////////
406
void ENC_NotifyChange(unsigned char encoder, char incrementer) __wparam
407
{
408
}
409
 
410
/////////////////////////////////////////////////////////////////////////////
411
// This function is called by MIOS when a pot has been moved
412
/////////////////////////////////////////////////////////////////////////////
413
void AIN_NotifyChange(unsigned char pin, unsigned int pin_value) __wparam
414
{
910 tk 415
  // a pot has been moved, send modulation CC#1
1194 tk 416
#if BLM_AIN_PIN_MAP
417
#warning "AIN Pin Map has been activated"
418
  pin = ain_pin_map[pin & 7];
419
#endif
910 tk 420
  MIOS_MIDI_TxBufferPut(0xb0 + (pin & 0x0f));
421
  MIOS_MIDI_TxBufferPut(0x01);
422
  MIOS_MIDI_TxBufferPut(MIOS_AIN_Pin7bitGet(pin));
859 tk 423
}
424
 
425
 
426
 
427
/////////////////////////////////////////////////////////////////////////////
428
// This function is NOT called by MIOS, but by the scan matrix handler
909 tk 429
// in $MIOS_PATH/modules/blm_scalar, when a pin of the scan matrix has been toggled
956 tk 430
// Note: in addition to "pin" and "value", the "blm_scalar_button_column" and
431
// "blm_scalar_button_row" are available as global variables (defined in blm.h)
909 tk 432
/////////////////////////////////////////////////////////////////////////////
433
void BLM_SCALAR_NotifyToggle(unsigned char pin, unsigned char value) __wparam
434
{
435
  unsigned char mask;
436
 
437
  // send pin number and value as Note On Event
910 tk 438
  if( blm_scalar_button_row < 0x20 ) {
439
    // BLM 16x16
1194 tk 440
#if BLM_MIRROR_MAIN_DIN
441
#warning "BLM Main DIN mirroring has been activated!"
442
    pin = (pin & 0x8) | (7 - pin);
443
#endif
910 tk 444
    MIOS_MIDI_TxBufferPut(0x90 + (pin >> 4));
445
    MIOS_MIDI_TxBufferPut(pin & 0x0f);
446
    MIOS_MIDI_TxBufferPut(value ? 0x00 : 0x7f);
447
  } else if( (blm_scalar_button_row & 0xf9) == 0x20 && blm_scalar_button_column < 4 ) {
448
    // Extra column
449
    unsigned char row = ((blm_scalar_button_row >> 1) & 3) | (blm_scalar_button_column << 2);
450
    MIOS_MIDI_TxBufferPut(0x90 + row);
451
    MIOS_MIDI_TxBufferPut(0x40);
452
    MIOS_MIDI_TxBufferPut(value ? 0x00 : 0x7f);
453
  } else if( (blm_scalar_button_row & 0xf9) == 0x21 ) {
454
    unsigned char column = ((blm_scalar_button_row << 1) & 0x0c) | (blm_scalar_button_column & 0x3);
455
    if( blm_scalar_button_column < 4 ) {
456
      // Extra row
457
      MIOS_MIDI_TxBufferPut(0x90);
458
      MIOS_MIDI_TxBufferPut(0x60 + column);
459
      MIOS_MIDI_TxBufferPut(value ? 0x00 : 0x7f);
460
    } else {
461
      // Additional extra buttons
462
      MIOS_MIDI_TxBufferPut(0x9f);
463
      MIOS_MIDI_TxBufferPut(0x60 + column);
464
      MIOS_MIDI_TxBufferPut(value ? 0x00 : 0x7f);
465
    }
466
  }
909 tk 467
 
910 tk 468
  // enable this to determine/debug the column/row scrambling
469
#if 0
470
  MIOS_MIDI_TxBufferPut(0xb0);
471
  MIOS_MIDI_TxBufferPut(blm_scalar_button_column);
472
  MIOS_MIDI_TxBufferPut(blm_scalar_button_row);
473
#endif
474
 
909 tk 475
  // enable this code (turn #if 0 into #if 1) if buttons should change the LED colour directly
476
  // disable it when LEDs should only be controlled via MIDI
910 tk 477
  if( testmode ) {
478
    // cycle colour whenever button has been pressed (value == 0)
479
    if( !value ) {
480
      mask = MIOS_HLP_GetBitORMask(blm_scalar_button_column);
481
      if ( blm_scalar_row_green[blm_scalar_button_row] & mask )
482
    blm_scalar_row_red[blm_scalar_button_row] ^= mask;
483
      blm_scalar_row_green[blm_scalar_button_row] ^= mask;
484
    }
909 tk 485
  }
486
}