Subversion Repositories svn.mios32

Rev

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

Rev Author Line No. Line
39 tk 1
// $Id: seq_lcd.c 2564 2018-03-03 21:31:17Z tk $
38 tk 2
/*
3
 * LCD utility functions
4
 *
821 tk 5
 * The 2x80 screen is buffered and can be output over multiple LCDs
6
 * (e.g. 2 * 2x40, but also 4 * 2x20)
7
 *
278 tk 8
 * The application should only access the displays via SEQ_LCD_* commands.
9
 *
10
 * The buffer method has the advantage, that multiple tasks can write to the
11
 * LCD without accessing the IO pins or the requirement for semaphores (to save time)
12
 *
13
 * Only changed characters (marked with flag 7 of each buffer byte) will be
14
 * transfered to the LCD. This greatly improves performance as well, especially
15
 * if a graphical display should ever be supported by MBSEQ, but also in the
16
 * emulation.
17
 *
18
 * Another advantage: LCD access works independent from the physical dimension
19
 * of the LCDs. They are combined to one large 2x80 display, and SEQ_LCD_Update()
20
 * will take care for switching between the devices and setting the cursor.
21
 * If different LCDs should be used, only SEQ_LCD_Update() needs to be changed.
22
 *
38 tk 23
 * ==========================================================================
24
 *
25
 *  Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
26
 *  Licensed for personal non-commercial use only.
27
 *  All other rights reserved.
28
 *
29
 * ==========================================================================
30
 */
31
 
32
/////////////////////////////////////////////////////////////////////////////
33
// Include files
34
/////////////////////////////////////////////////////////////////////////////
35
 
36
#include <mios32.h>
278 tk 37
#include <stdarg.h>
353 tk 38
#include "tasks.h"
38 tk 39
 
40
#include "seq_lcd.h"
626 tk 41
#include "seq_ui.h"
285 tk 42
#include "seq_midi_port.h"
626 tk 43
#include "seq_midi_sysex.h"
326 tk 44
#include "seq_cc.h"
1142 tk 45
#include "seq_par.h"
46
#include "seq_layer.h"
2020 tk 47
#include "seq_scale.h"
38 tk 48
 
49
/////////////////////////////////////////////////////////////////////////////
50
// Global variables
51
/////////////////////////////////////////////////////////////////////////////
52
 
278 tk 53
/////////////////////////////////////////////////////////////////////////////
54
// Local definitions
55
/////////////////////////////////////////////////////////////////////////////
38 tk 56
 
821 tk 57
// can be overruled in mios32_config.h
58
#ifndef LCD_NUM_DEVICES
59
# define LCD_NUM_DEVICES          2
60
#endif
61
 
62
#ifndef LCD_COLUMNS_PER_DEVICE
63
# define LCD_COLUMNS_PER_DEVICE  40
64
#endif
65
 
66
 
67
// shouldn't be overruled
278 tk 68
#define LCD_MAX_LINES    2
821 tk 69
#define LCD_MAX_COLUMNS  (LCD_NUM_DEVICES*LCD_COLUMNS_PER_DEVICE)
278 tk 70
 
71
 
821 tk 72
 
38 tk 73
/////////////////////////////////////////////////////////////////////////////
74
// Local variables
75
/////////////////////////////////////////////////////////////////////////////
76
 
744 tk 77
static const u8 charset_menu[64] = {
78
  0x01, 0x03, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, // left-arrow
79
  0x00, 0x00, 0x00, 0x10, 0x18, 0x1c, 0x18, 0x10, // right-arrow
80
  0x01, 0x03, 0x07, 0x13, 0x19, 0x1c, 0x18, 0x10, // left/right arrow
81
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // spare
82
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // spare
83
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // spare
84
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // spare
85
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // spare
86
};
87
 
278 tk 88
static const u8 charset_vbars[64] = {
38 tk 89
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
90
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e,
91
  0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e, 0x1e,
92
  0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e,
93
  0x00, 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
94
  0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
95
  0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
96
  0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e
97
};
98
 
278 tk 99
static const u8 charset_hbars[64] = {
176 tk 100
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // empty bar
101
  0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, // "|  "
102
  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, // "|| "
103
  0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, // "|||"
104
  0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, // " o "
105
  0x00, 0x10, 0x14, 0x15, 0x15, 0x14, 0x10, 0x00, // " > "
106
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // not used
107
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // not used
108
};
38 tk 109
 
325 tk 110
static const u8 charset_drum_symbols_big[64] = {
111
  0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, // dot
112
  0x00, 0x04, 0x0e, 0x1f, 0x1f, 0x0e, 0x04, 0x00, // full
113
  0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e, 0x00, // outlined
327 tk 114
  0x00, 0x0e, 0x11, 0x15, 0x15, 0x11, 0x0e, 0x00, // outlined with dot
323 tk 115
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325 tk 117
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323 tk 119
};
120
 
325 tk 121
static const u8 charset_drum_symbols_medium[64] = {
122
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // no dot
123
  0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, // left dot
124
  0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, // right dot
125
  0x00, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x00, // both dots
126
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130
};
131
 
132
static const u8 charset_drum_symbols_small[64] = {
133
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0
134
  0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, // 1
135
  0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, // 2
136
  0x00, 0x00, 0x00, 0x14, 0x14, 0x00, 0x00, 0x00, // 3
137
  0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, // 4
138
  0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, // 5
139
  0x00, 0x00, 0x00, 0x14, 0x14, 0x00, 0x00, 0x00, // 6
140
  0x00, 0x00, 0x00, 0x15, 0x15, 0x00, 0x00, 0x00, // 7
141
};
142
 
278 tk 143
static u8 lcd_buffer[LCD_MAX_LINES][LCD_MAX_COLUMNS];
176 tk 144
 
278 tk 145
static u16 lcd_cursor_x;
146
static u16 lcd_cursor_y;
147
 
2130 tk 148
static seq_lcd_charset_t seq_lcd_current_charset = SEQ_LCD_CHARSET_None;
278 tk 149
 
2130 tk 150
 
38 tk 151
/////////////////////////////////////////////////////////////////////////////
821 tk 152
// Display Initialisation
153
/////////////////////////////////////////////////////////////////////////////
154
s32 SEQ_LCD_Init(u32 mode)
155
{
156
  u8 dev;
157
 
2266 tk 158
  // first two LCDs already initialized in main.c
159
  // for the case that more than two LCDs have been configured:
160
  for(dev=2; dev<LCD_NUM_DEVICES; ++dev) {
821 tk 161
    MIOS32_LCD_DeviceSet(dev);
162
    MIOS32_LCD_Init(0);
163
  }
164
 
165
  // switch back to first LCD
166
  MIOS32_LCD_DeviceSet(0);
167
 
168
  return 0; // no error
169
}
170
 
171
 
172
/////////////////////////////////////////////////////////////////////////////
278 tk 173
// Buffer handling functions
38 tk 174
/////////////////////////////////////////////////////////////////////////////
278 tk 175
 
176
// clears the buffer
38 tk 177
s32 SEQ_LCD_Clear(void)
178
{
179
  int i;
278 tk 180
 
181
  u8 *ptr = (u8 *)lcd_buffer;
182
  for(i=0; i<LCD_MAX_LINES*LCD_MAX_COLUMNS; ++i)
183
    *ptr++ = ' ';
38 tk 184
 
278 tk 185
  lcd_cursor_x = 0;
186
  lcd_cursor_y = 0;
187
 
188
  return 0; // no error
189
}
190
 
191
// prints char into buffer and increments cursor
192
s32 SEQ_LCD_PrintChar(char c)
193
{
194
  if( lcd_cursor_y >= LCD_MAX_LINES || lcd_cursor_x >= LCD_MAX_COLUMNS )
195
    return -1; // invalid cursor range
196
 
197
  u8 *ptr = &lcd_buffer[lcd_cursor_y][lcd_cursor_x++];
198
  if( (*ptr & 0x7f) != c )
199
      *ptr = c;
200
 
201
  return 0; // no error
202
}
203
 
204
// allows to change the buffer from other tasks w/o the need for semaphore handling
205
// it doesn't change the cursor
206
s32 SEQ_LCD_BufferSet(u16 x, u16 y, char *str)
207
{
208
  // we assume, that the CPU allows atomic accesses to bytes, 
209
  // therefore no thread locking is required
210
 
211
  if( lcd_cursor_y >= LCD_MAX_LINES )
212
    return -1; // invalid cursor range
213
 
214
  u8 *ptr = &lcd_buffer[y][x];
215
  while( *str != '\0' ) {
216
    if( x++ >= LCD_MAX_COLUMNS )
217
      break;
218
    if( (*ptr & 0x7f) != *str )
219
      *ptr = *str;
220
    ++ptr;
221
    ++str;
38 tk 222
  }
223
 
278 tk 224
  return 0; // no error
225
}
38 tk 226
 
278 tk 227
// sets the cursor to a new buffer location
228
s32 SEQ_LCD_CursorSet(u16 column, u16 line)
229
{
230
  // set character position
231
  lcd_cursor_x = column;
232
  lcd_cursor_y = line;
233
 
234
  return 0;
235
}
236
 
237
// transfers the buffer to LCDs
238
// if force != 0, it is ensured that the whole screen will be refreshed, regardless
239
// if characters have changed or not
240
s32 SEQ_LCD_Update(u8 force)
241
{
242
  int next_x = -1;
243
  int next_y = -1;
626 tk 244
  int remote_first_x[LCD_MAX_LINES];
245
  int remote_last_x[LCD_MAX_LINES];
246
  int x, y;
278 tk 247
 
626 tk 248
  for(y=0; y<2; ++y) {
249
    remote_first_x[y] = -1;
250
    remote_last_x[y] = -1;
251
  }
252
 
353 tk 253
  MUTEX_LCD_TAKE;
254
 
278 tk 255
  u8 *ptr = (u8 *)lcd_buffer;
256
  for(y=0; y<LCD_MAX_LINES; ++y)
257
    for(x=0; x<LCD_MAX_COLUMNS; ++x) {
258
 
259
      if( force || !(*ptr & 0x80) ) {
626 tk 260
    if( remote_first_x[y] == -1 )
261
      remote_first_x[y] = x;
262
    remote_last_x[y] = x;
263
 
278 tk 264
    if( x != next_x || y != next_y ) {
821 tk 265
      MIOS32_LCD_DeviceSet(x / LCD_COLUMNS_PER_DEVICE);
266
      MIOS32_LCD_CursorSet(x % LCD_COLUMNS_PER_DEVICE, y);
278 tk 267
    }
268
    MIOS32_LCD_PrintChar(*ptr & 0x7f);
761 tk 269
 
762 tk 270
    MIOS32_IRQ_Disable(); // must be atomic
278 tk 271
    *ptr |= 0x80;
762 tk 272
    MIOS32_IRQ_Enable();
273
 
278 tk 274
    next_y = y;
275
    next_x = x+1;
276
 
821 tk 277
    // for multiple LCDs: ensure that cursor is set when we reach the next partition
278
    if( (next_x % LCD_COLUMNS_PER_DEVICE) == 0 )
278 tk 279
      next_x = -1;
280
      }
281
      ++ptr;
282
    }
283
 
353 tk 284
  MUTEX_LCD_GIVE;
285
 
626 tk 286
  // forward display changes to remote client
1316 tk 287
  if( seq_midi_sysex_remote_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_SERVER || seq_midi_sysex_remote_active_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_SERVER ) {
626 tk 288
    for(y=0; y<LCD_MAX_LINES; ++y)
289
      if( remote_first_x[y] >= 0 )
290
    SEQ_MIDI_SYSEX_REMOTE_Server_SendLCD(remote_first_x[y],
291
                         y,
292
                         (u8 *)&lcd_buffer[y][remote_first_x[y]],
293
                         remote_last_x[y]-remote_first_x[y]+1);
294
  }
295
 
38 tk 296
  return 0; // no error
297
}
298
 
299
 
300
/////////////////////////////////////////////////////////////////////////////
301
// initialise character set (if not already active)
302
/////////////////////////////////////////////////////////////////////////////
176 tk 303
s32 SEQ_LCD_InitSpecialChars(seq_lcd_charset_t charset)
38 tk 304
{
353 tk 305
  s32 status = 0;
176 tk 306
 
2130 tk 307
  if( charset != seq_lcd_current_charset ) {
308
    seq_lcd_current_charset = charset;
38 tk 309
 
353 tk 310
    MUTEX_LCD_TAKE;
134 tk 311
    int dev;
821 tk 312
    for(dev=0; dev<LCD_NUM_DEVICES; ++dev) {
134 tk 313
      MIOS32_LCD_DeviceSet(dev);
314
      switch( charset ) {
744 tk 315
        case SEQ_LCD_CHARSET_Menu:
316
      MIOS32_LCD_SpecialCharsInit((u8 *)charset_menu);
317
      break;
176 tk 318
        case SEQ_LCD_CHARSET_VBars:
134 tk 319
      MIOS32_LCD_SpecialCharsInit((u8 *)charset_vbars);
320
      break;
176 tk 321
        case SEQ_LCD_CHARSET_HBars:
322
      MIOS32_LCD_SpecialCharsInit((u8 *)charset_hbars);
323
      break;
325 tk 324
        case SEQ_LCD_CHARSET_DrumSymbolsBig:
325
      MIOS32_LCD_SpecialCharsInit((u8 *)charset_drum_symbols_big);
323 tk 326
      break;
325 tk 327
        case SEQ_LCD_CHARSET_DrumSymbolsMedium:
328
      MIOS32_LCD_SpecialCharsInit((u8 *)charset_drum_symbols_medium);
329
      break;
330
        case SEQ_LCD_CHARSET_DrumSymbolsSmall:
331
      MIOS32_LCD_SpecialCharsInit((u8 *)charset_drum_symbols_small);
332
      break;
134 tk 333
        default:
353 tk 334
      status = -1; // charset doesn't exist
134 tk 335
      }
38 tk 336
    }
353 tk 337
 
338
    MUTEX_LCD_GIVE;
626 tk 339
 
340
    // forward charset change to remote client
1316 tk 341
    if( seq_midi_sysex_remote_mode == SEQ_MIDI_SYSEX_REMOTE_MODE_SERVER )
626 tk 342
      SEQ_MIDI_SYSEX_REMOTE_Server_SendCharset(charset);
38 tk 343
  }
344
 
353 tk 345
  return status; // no error
38 tk 346
}
347
 
2130 tk 348
/////////////////////////////////////////////////////////////////////////////
349
// re-initialise character set
350
/////////////////////////////////////////////////////////////////////////////
351
s32 SEQ_LCD_ReInitSpecialChars(void)
352
{
353
  seq_lcd_charset_t charset = seq_lcd_current_charset;
354
 
355
  SEQ_LCD_InitSpecialChars(SEQ_LCD_CHARSET_None);
356
  SEQ_LCD_InitSpecialChars(charset);
38 tk 357
 
2130 tk 358
  return 0; // no error
359
}
360
 
361
 
38 tk 362
/////////////////////////////////////////////////////////////////////////////
278 tk 363
// prints a string
364
/////////////////////////////////////////////////////////////////////////////
2039 tk 365
s32 SEQ_LCD_PrintString(const char *str)
278 tk 366
{
367
  while( *str != '\0' ) {
368
    if( lcd_cursor_x >= LCD_MAX_COLUMNS )
369
      break;
370
    SEQ_LCD_PrintChar(*str);
371
    ++str;
372
  }
373
 
374
  return 0; // no error
375
}
376
 
316 tk 377
 
278 tk 378
/////////////////////////////////////////////////////////////////////////////
379
// prints a formatted string
380
/////////////////////////////////////////////////////////////////////////////
2039 tk 381
s32 SEQ_LCD_PrintFormattedString(const char *format, ...)
278 tk 382
{
383
  char buffer[LCD_MAX_COLUMNS]; // TODO: tmp!!! Provide a streamed COM method later!
384
  va_list args;
385
 
386
  va_start(args, format);
387
  vsprintf((char *)buffer, format, args);
388
  return SEQ_LCD_PrintString(buffer);
389
}
390
 
391
 
392
/////////////////////////////////////////////////////////////////////////////
38 tk 393
// prints <num> spaces
394
/////////////////////////////////////////////////////////////////////////////
1250 tk 395
s32 SEQ_LCD_PrintSpaces(int num)
38 tk 396
{
1250 tk 397
  while( num > 0 ) {
278 tk 398
    SEQ_LCD_PrintChar(' ');
1250 tk 399
    --num;
400
  }
38 tk 401
 
402
  return 0; // no error
403
}
404
 
405
 
406
/////////////////////////////////////////////////////////////////////////////
272 tk 407
// prints padded string
408
/////////////////////////////////////////////////////////////////////////////
409
s32 SEQ_LCD_PrintStringPadded(char *str, u32 width)
410
{
411
  // replacement for not supported "%:-40s" of simple sprintf function
412
 
413
  u32 pos;
414
  u8 fill = 0;
415
  for(pos=0; pos<width; ++pos) {
416
    char c = str[pos];
417
    if( c == 0 )
418
      fill = 1;
316 tk 419
    SEQ_LCD_PrintChar(fill ? ' ' : c);
272 tk 420
  }
421
 
422
  return 0; // no error
423
}
424
 
425
 
426
/////////////////////////////////////////////////////////////////////////////
176 tk 427
// prints a vertical bar for a 3bit value
428
// (1 character)
429
/////////////////////////////////////////////////////////////////////////////
430
s32 SEQ_LCD_PrintVBar(u8 value)
431
{
278 tk 432
  return SEQ_LCD_PrintChar(value);
176 tk 433
}
434
 
435
 
436
/////////////////////////////////////////////////////////////////////////////
437
// prints a horizontal bar for a 4bit value
438
// (5 characters)
439
/////////////////////////////////////////////////////////////////////////////
440
s32 SEQ_LCD_PrintHBar(u8 value)
441
{
442
  // special chars which should be print depending on meter value (16 entries, only 14 used)
443
  const u8 hbar_table[16][5] = {
444
    { 4, 0, 0, 0, 0 },
445
    { 1, 0, 0, 0, 0 },
446
    { 2, 0, 0, 0, 0 },
447
    { 3, 0, 0, 0, 0 },
448
    { 3, 1, 0, 0, 0 },
449
    { 3, 2, 0, 0, 0 },
450
    { 3, 3, 0, 0, 0 },
451
    { 3, 3, 1, 0, 0 },
452
    { 3, 3, 2, 0, 0 },
453
    { 3, 3, 3, 0, 0 },
454
    { 3, 3, 3, 1, 0 },
455
    { 3, 3, 3, 2, 0 },
456
    { 3, 3, 3, 3, 1 },
457
    { 3, 3, 3, 3, 2 },
458
    { 3, 3, 3, 3, 3 },
459
    { 3, 3, 3, 3, 3 }
460
  };
461
 
462
  int i;
463
  for(i=0; i<5; ++i)
278 tk 464
    SEQ_LCD_PrintChar(hbar_table[value][i]);
176 tk 465
 
466
  return 0; // no error
467
}
468
 
469
 
470
/////////////////////////////////////////////////////////////////////////////
473 tk 471
// prints a long horizontal bar for a 7bit value
472
// (32 characters)
473
/////////////////////////////////////////////////////////////////////////////
474
s32 SEQ_LCD_PrintLongHBar(u8 value)
475
{
476
  int i;
477
 
478
  const u8 hbar_table[4] = { 1, 2, 3, 3 };
479
 
480
  for(i=0; i<32; ++i) {
481
    if( (value/4) < i )
482
      SEQ_LCD_PrintChar(' ');
483
    else if( (value/4) > i )
484
      SEQ_LCD_PrintChar(3);
485
    else
486
      SEQ_LCD_PrintChar(hbar_table[value%4]);
487
  }
488
 
489
  return 0; // no error
490
}
491
 
492
 
493
/////////////////////////////////////////////////////////////////////////////
38 tk 494
// prints a note string (3 characters)
495
/////////////////////////////////////////////////////////////////////////////
496
s32 SEQ_LCD_PrintNote(u8 note)
497
{
498
  const char note_tab[12][3] = { "c-", "c#", "d-", "d#", "e-", "f-", "f#", "g-", "g#", "a-", "a#", "b-" };
499
 
500
  // print "---" if note number is 0
501
  if( note == 0 )
278 tk 502
    SEQ_LCD_PrintString("---");
38 tk 503
  else {
504
    // determine octave, note contains semitone number thereafter
1292 tk 505
    u8 octave = note / 12;
506
    note %= 12;
38 tk 507
 
508
    // print semitone (capital letter if octave >= 2)
278 tk 509
    SEQ_LCD_PrintChar(octave >= 2 ? (note_tab[note][0] + 'A'-'a') : note_tab[note][0]);
510
    SEQ_LCD_PrintChar(note_tab[note][1]);
38 tk 511
 
512
    // print octave
513
    switch( octave ) {
278 tk 514
      case 0:  SEQ_LCD_PrintChar('2'); break; // -2
515
      case 1:  SEQ_LCD_PrintChar('1'); break; // -1
516
      default: SEQ_LCD_PrintChar('0' + (octave-2)); // 0..7
38 tk 517
    }
518
  }
519
 
520
  return 0; // no error
521
}
522
 
523
 
524
/////////////////////////////////////////////////////////////////////////////
182 tk 525
// prints an arp event (3 characters)
526
/////////////////////////////////////////////////////////////////////////////
527
s32 SEQ_LCD_PrintArp(u8 arp)
528
{
529
  if( arp < 4 )
278 tk 530
    SEQ_LCD_PrintString("---");
182 tk 531
  else {
532
    int key_num = (arp >> 2) & 0x3;
533
    int arp_oct = (arp >> 4) & 0x7;
534
 
535
    if( arp_oct < 2 ) { // Multi Arp
278 tk 536
      SEQ_LCD_PrintChar('*');
182 tk 537
      arp_oct = ((arp >> 2) & 7) - 4;
538
    } else {
278 tk 539
      SEQ_LCD_PrintChar('1' + key_num);
182 tk 540
      arp_oct -= 4;
541
    }
542
 
543
    if( arp_oct >= 0 )
278 tk 544
      SEQ_LCD_PrintFormattedString("+%d", arp_oct);
182 tk 545
    else
278 tk 546
      SEQ_LCD_PrintFormattedString("-%d", -arp_oct);
182 tk 547
  }
548
 
549
  return 0; // no error
550
}
551
 
552
 
553
/////////////////////////////////////////////////////////////////////////////
38 tk 554
// prints the gatelength (4 characters)
555
/////////////////////////////////////////////////////////////////////////////
556
s32 SEQ_LCD_PrintGatelength(u8 len)
557
{
338 tk 558
  if( len < 96 ) {
330 tk 559
    int len_percent = (len*100)/96;
560
    SEQ_LCD_PrintFormattedString("%3d%%", len_percent);
561
  } else { // gilde
278 tk 562
    SEQ_LCD_PrintString("Gld.");
38 tk 563
  }
564
 
565
  return 0; // no error
566
}
567
 
568
 
569
/////////////////////////////////////////////////////////////////////////////
333 tk 570
// prints the probability value (4 characters)
571
/////////////////////////////////////////////////////////////////////////////
572
s32 SEQ_LCD_PrintProbability(u8 probability)
573
{
574
  return SEQ_LCD_PrintFormattedString("%3d%%", probability);
575
}
576
 
577
 
578
/////////////////////////////////////////////////////////////////////////////
579
// prints the step delay value (4 characters)
580
/////////////////////////////////////////////////////////////////////////////
581
s32 SEQ_LCD_PrintStepDelay(s32 delay)
582
{
583
  return SEQ_LCD_PrintFormattedString("%3d ", delay);
584
}
585
 
586
 
587
/////////////////////////////////////////////////////////////////////////////
588
// prints the roll mode (4 characters)
589
/////////////////////////////////////////////////////////////////////////////
590
s32 SEQ_LCD_PrintRollMode(u8 roll_mode)
591
{
592
  if( roll_mode == 0 )
593
    return SEQ_LCD_PrintString("----");
594
 
595
  return SEQ_LCD_PrintFormattedString("%d%c%02d",
596
                      ((roll_mode & 0x30)>>4) + 2,
334 tk 597
                      (roll_mode & 0x40) ? 'U' : 'D',
598
                      roll_mode&0xf);
333 tk 599
}
600
 
601
 
602
/////////////////////////////////////////////////////////////////////////////
1024 tk 603
// prints the roll2 mode (4 characters)
604
/////////////////////////////////////////////////////////////////////////////
605
s32 SEQ_LCD_PrintRoll2Mode(u8 roll2_mode)
606
{
607
  if( roll2_mode == 0 )
608
    return SEQ_LCD_PrintString("----");
609
 
610
  int gatelength = (4 - (roll2_mode >> 5)) * ((roll2_mode&0x1f)+1);
611
 
612
  if( gatelength > 96 ) {
613
    return SEQ_LCD_PrintFormattedString("%dx++", (roll2_mode>>5) + 2);
614
  }
615
 
616
  return SEQ_LCD_PrintFormattedString("%dx%02d", (roll2_mode>>5) + 2, gatelength);
617
}
618
 
619
 
620
/////////////////////////////////////////////////////////////////////////////
2159 tk 621
// prints the Nth mode (4 characters)
622
/////////////////////////////////////////////////////////////////////////////
623
s32 SEQ_LCD_PrintNthValue(u8 nth_value)
624
{
625
  if( nth_value == 0 )
626
    return SEQ_LCD_PrintString("----");
627
 
628
  // NOTE: characters have to be aligned with the SEQ_PAR_TYPE_NTH_* numbers in seq_par.h!
629
  const char nth_char1[8] = { '-', 'M', 'P', 'A', 'R', 'F', 'N', '?' };
630
  const char nth_char2[8] = { '-', 'u', 'l', 'c', 'o', 'x', 'x', '?' };
631
 
632
  int bars = (nth_value & 0xf) + 1;
633
  int mode = (nth_value >> 4) & 0x7;
634
 
2160 tk 635
  return SEQ_LCD_PrintFormattedString("%c%c%2d", nth_char1[mode], nth_char2[mode], bars);
2159 tk 636
}
637
 
638
 
639
/////////////////////////////////////////////////////////////////////////////
2435 tk 640
// prints the Root value (4 characters)
641
/////////////////////////////////////////////////////////////////////////////
642
s32 SEQ_LCD_PrintRootValue(u8 root_value)
643
{
644
  const char keys_str[13][5] = { // note: this array is also used to determine halfnotes, don't touch it (or some code needs to be adapted below)
2437 tk 645
    "Glb ", " C  ", " C# ", " D  ", " D# ", " E  ", " F  ", " F# ", " G  ", " G# ", " A  ", " A# ", " B  "
2435 tk 646
  };
647
 
648
  return SEQ_LCD_PrintFormattedString((char *)keys_str[root_value % 13]);
649
}
650
 
651
 
652
/////////////////////////////////////////////////////////////////////////////
653
// prints the Scale value (4 characters)
654
/////////////////////////////////////////////////////////////////////////////
655
s32 SEQ_LCD_PrintScaleValue(u8 scale_value)
656
{
657
  if( scale_value == 0 ) {
658
    return SEQ_LCD_PrintFormattedString("Glb ");
659
  }
660
 
661
  return SEQ_LCD_PrintFormattedString("%3d ", scale_value-1);
662
}
663
 
664
 
665
/////////////////////////////////////////////////////////////////////////////
759 tk 666
// prints event type of MIDI package with given number of chars
667
/////////////////////////////////////////////////////////////////////////////
668
s32 SEQ_LCD_PrintEvent(mios32_midi_package_t package, u8 num_chars)
669
{
670
  // currently only 5 chars supported...
671
  if( package.type == 0xf || package.evnt0 >= 0xf8 ) {
672
    switch( package.evnt0 ) {
673
      case 0xf8: SEQ_LCD_PrintString(" CLK "); break;
674
      case 0xfa: SEQ_LCD_PrintString("START"); break;
675
      case 0xfb: SEQ_LCD_PrintString("CONT."); break;
676
      case 0xfc: SEQ_LCD_PrintString("STOP "); break;
677
      default:
678
    SEQ_LCD_PrintFormattedString(" %02X  ", package.evnt0);
679
    }
680
  } else if( package.type < 8 ) {
681
    SEQ_LCD_PrintString("SysEx");
682
  } else {
683
    switch( package.event ) {
684
      case NoteOff:
685
      case NoteOn:
686
      case PolyPressure:
687
      case CC:
688
      case ProgramChange:
689
      case Aftertouch:
690
      case PitchBend:
691
    // could be enhanced later
692
        SEQ_LCD_PrintFormattedString("%02X%02X ", package.evnt0, package.evnt1);
693
    break;
694
 
695
      default:
696
    // print first two bytes for unsupported events
697
        SEQ_LCD_PrintFormattedString("%02X%02X ", package.evnt0, package.evnt1);
698
    }
699
  }
700
 
701
  // TODO: enhanced messages
702
  if( num_chars > 5 )
703
    SEQ_LCD_PrintSpaces(num_chars-5);
704
 
705
  return 0; // no error
706
}
707
 
708
 
709
/////////////////////////////////////////////////////////////////////////////
1142 tk 710
// prints layer event
711
/////////////////////////////////////////////////////////////////////////////
2192 tk 712
s32 SEQ_LCD_PrintLayerValue(u8 track, u8 par_layer, u8 par_value)
713
{
714
  seq_par_layer_type_t layer_type = SEQ_PAR_AssignmentGet(track, par_layer);
715
 
716
  // TODO: tmp. solution to print chord velocity correctly
717
  if( layer_type == SEQ_PAR_Type_Velocity && (seq_cc_trk[track].link_par_layer_chord == 0) )
2274 tk 718
    layer_type = SEQ_PAR_Type_Chord1;
2192 tk 719
 
720
  switch( layer_type ) {
721
  case SEQ_PAR_Type_None:
722
    SEQ_LCD_PrintString("None");
723
    break;
724
 
725
  case SEQ_PAR_Type_Note:
726
  case SEQ_PAR_Type_Velocity: {
727
    if( layer_type == SEQ_PAR_Type_Note ) {
728
      if( par_value ) {
729
    if( SEQ_CC_Get(track, SEQ_CC_MODE) == SEQ_CORE_TRKMODE_Arpeggiator )
730
      SEQ_LCD_PrintArp(par_value);
731
    else
732
      SEQ_LCD_PrintNote(par_value);
733
    SEQ_LCD_PrintChar(' ');
734
      } else {
735
    SEQ_LCD_PrintString("----");
736
      }
737
    } else {
738
      SEQ_LCD_PrintFormattedString("%3d ", par_value);
739
    }
740
  } break;
741
 
2274 tk 742
  case SEQ_PAR_Type_Chord1:
743
  case SEQ_PAR_Type_Chord2: {
2192 tk 744
    if( par_value ) {
745
      u8 chord_ix = par_value & 0x1f;
746
      u8 chord_char = ((chord_ix >= 0x10) ? 'a' : 'A') + (chord_ix & 0xf);
747
      u8 chord_oct = par_value >> 5;
748
      SEQ_LCD_PrintFormattedString("%c/%d ", chord_char, chord_oct);
749
    } else {
750
      SEQ_LCD_PrintString("----");
751
    }
752
  } break;
753
 
2505 tk 754
  case SEQ_PAR_Type_Chord3: {
755
    if( par_value ) {
756
      if( par_value < 100 ) {
757
    SEQ_LCD_PrintFormattedString("Ch%2d", par_value);
758
      } else {
759
    SEQ_LCD_PrintFormattedString("C%3d", par_value);
760
      }
761
    } else {
762
      SEQ_LCD_PrintString("----");
763
    }
764
  } break;
765
 
2192 tk 766
  case SEQ_PAR_Type_Length:
767
    SEQ_LCD_PrintGatelength(par_value);
768
    break;
769
 
770
  case SEQ_PAR_Type_CC:
771
  case SEQ_PAR_Type_ProgramChange:
2389 tk 772
  case SEQ_PAR_Type_PitchBend:
773
  case SEQ_PAR_Type_Aftertouch: {
2192 tk 774
    if( par_value >= 0x80 ) {
2448 tk 775
      SEQ_LCD_PrintFormattedString("----");
2192 tk 776
    } else {
777
      SEQ_LCD_PrintFormattedString("%3d ", par_value);
778
    }
779
  } break;
780
 
781
  case SEQ_PAR_Type_Probability:
782
    SEQ_LCD_PrintProbability(par_value);
783
    break;
784
 
785
  case SEQ_PAR_Type_Delay:
786
    SEQ_LCD_PrintStepDelay(par_value);
787
    break;
788
 
789
  case SEQ_PAR_Type_Roll:
790
    SEQ_LCD_PrintRollMode(par_value);
791
    break;
792
 
793
  case SEQ_PAR_Type_Roll2:
794
    SEQ_LCD_PrintRoll2Mode(par_value);
795
    break;
796
 
797
  case SEQ_PAR_Type_Nth1:
798
    SEQ_LCD_PrintNthValue(par_value);
799
    break;
800
 
801
  case SEQ_PAR_Type_Nth2:
802
    SEQ_LCD_PrintNthValue(par_value);
803
    break;
804
 
2435 tk 805
  case SEQ_PAR_Type_Root:
806
    SEQ_LCD_PrintRootValue(par_value);
807
    break;
808
 
809
  case SEQ_PAR_Type_Scale:
810
    SEQ_LCD_PrintScaleValue(par_value);
811
    break;
812
 
2192 tk 813
  default:
814
    SEQ_LCD_PrintString("????");
815
    break;
816
  }
817
 
818
  return 0; // no error
819
}
820
 
821
/////////////////////////////////////////////////////////////////////////////
822
// prints layer event
823
/////////////////////////////////////////////////////////////////////////////
1351 tk 824
s32 SEQ_LCD_PrintLayerEvent(u8 track, u8 step, u8 par_layer, u8 instrument, u8 step_view, int print_edit_value)
1142 tk 825
{
2521 tk 826
  seq_core_trk_t *t = &seq_core_trk[track];
2435 tk 827
  seq_cc_trk_t *tcc = &seq_cc_trk[track];
1142 tk 828
  seq_par_layer_type_t layer_type = SEQ_PAR_AssignmentGet(track, par_layer);
829
  u8 event_mode = SEQ_CC_Get(track, SEQ_CC_MIDI_EVENT_MODE);
830
  seq_layer_evnt_t layer_event;
831
  SEQ_LAYER_GetEvntOfLayer(track, step, par_layer, instrument, &layer_event);
832
 
2564 tk 833
  u8 print_without_gate = seq_ui_options.PRINT_AND_MODIFY_WITHOUT_GATES;
834
 
1278 tk 835
  // TODO: tmp. solution to print chord velocity correctly
836
  if( layer_type == SEQ_PAR_Type_Velocity && (seq_cc_trk[track].link_par_layer_chord == 0) )
2521 tk 837
    layer_type = tcc->lay_const[0];
1278 tk 838
 
1142 tk 839
  switch( layer_type ) {
840
  case SEQ_PAR_Type_None:
841
    SEQ_LCD_PrintString("None");
842
    break;
843
 
844
  case SEQ_PAR_Type_Note:
1351 tk 845
  case SEQ_PAR_Type_Velocity: {
2564 tk 846
    if( layer_event.midi_package.note == 0 || (!print_without_gate && layer_event.midi_package.velocity == 0) ) {
2538 tk 847
      SEQ_LCD_PrintString("----");
848
      break;
849
    }
850
 
851
    if( print_edit_value >= 0 ) {
852
      if( layer_type == SEQ_PAR_Type_Note ) {
853
    layer_event.midi_package.note = print_edit_value;
854
      } else if( layer_type == SEQ_PAR_Type_Velocity ) {
855
    layer_event.midi_package.velocity = print_edit_value;
856
      }
857
    }
858
 
2564 tk 859
    if( tcc->playmode != SEQ_CORE_TRKMODE_Arpeggiator && layer_event.midi_package.note > 0 && (print_without_gate || layer_event.midi_package.velocity > 0) ) {
2523 tk 860
      // transpose notes/CCs
861
      SEQ_CORE_Transpose(track, instrument, t, tcc, &layer_event.midi_package);
2536 tk 862
 
863
      if( seq_cc_trk[track].trkmode_flags.FORCE_SCALE && layer_type != SEQ_PAR_Type_Chord1 && layer_type != SEQ_PAR_Type_Chord2 && layer_type != SEQ_PAR_Type_Chord3 ) {
864
    if( layer_event.midi_package.note ) {
865
      u8 scale, root_selection, root;
866
      SEQ_CORE_FTS_GetScaleAndRoot(track, step, instrument, tcc, &scale, &root_selection, &root);
867
      SEQ_SCALE_Note(&layer_event.midi_package, scale, root);
868
    }      
869
      }
2523 tk 870
    }
2521 tk 871
 
1142 tk 872
    if( step_view ) {
873
      if( layer_event.midi_package.note &&
2564 tk 874
      (print_edit_value >= 0 || print_without_gate || (layer_event.midi_package.velocity && SEQ_TRG_GateGet(track, step, instrument))) ) {
1142 tk 875
    if( SEQ_CC_Get(track, SEQ_CC_MODE) == SEQ_CORE_TRKMODE_Arpeggiator )
2538 tk 876
      SEQ_LCD_PrintArp(layer_event.midi_package.note);
1142 tk 877
    else
2538 tk 878
      SEQ_LCD_PrintNote(layer_event.midi_package.note);
1142 tk 879
    SEQ_LCD_PrintVBar(layer_event.midi_package.velocity >> 4);
880
      } else {
881
    SEQ_LCD_PrintString("----");
882
      }
883
    } else {
884
      if( layer_type == SEQ_PAR_Type_Note ) {
2538 tk 885
    if( layer_event.midi_package.note ) {
1142 tk 886
      if( SEQ_CC_Get(track, SEQ_CC_MODE) == SEQ_CORE_TRKMODE_Arpeggiator )
2538 tk 887
        SEQ_LCD_PrintArp(layer_event.midi_package.note);
1142 tk 888
      else
2538 tk 889
        SEQ_LCD_PrintNote(layer_event.midi_package.note);
1142 tk 890
      SEQ_LCD_PrintChar(' ');
891
    } else {
892
      SEQ_LCD_PrintString("----");
893
    }
894
      } else {
895
    SEQ_LCD_PrintFormattedString("%3d", layer_event.midi_package.velocity);
896
    SEQ_LCD_PrintVBar(layer_event.midi_package.velocity >> 4);
897
      }
898
    }
1351 tk 899
  } break;
1142 tk 900
 
2274 tk 901
  case SEQ_PAR_Type_Chord1:
2505 tk 902
  case SEQ_PAR_Type_Chord2:
903
  case SEQ_PAR_Type_Chord3: {
1143 tk 904
    u8 par_value;
2505 tk 905
    // more or less dirty - a velocity layer can force SEQ_PAR_Type_Chord[123]
1143 tk 906
    if( SEQ_PAR_AssignmentGet(track, par_layer) == SEQ_PAR_Type_Velocity )
1219 tk 907
      par_value = SEQ_PAR_ChordGet(track, step, instrument, 0x0000);
1143 tk 908
    else
1351 tk 909
      par_value = (print_edit_value >= 0) ? print_edit_value : SEQ_PAR_Get(track, step, par_layer, instrument);
1143 tk 910
 
2564 tk 911
    if( par_value && (print_edit_value >= 0 || print_without_gate || SEQ_TRG_GateGet(track, step, instrument)) ) {
2505 tk 912
      if( layer_type == SEQ_PAR_Type_Chord3 ) {
2510 tk 913
    if( par_value < 10 ) {
914
      SEQ_LCD_PrintFormattedString("Ch%d", par_value);
915
    } else if( par_value < 100 ) {
916
      SEQ_LCD_PrintFormattedString("C%2d", par_value);
2505 tk 917
    } else {
2510 tk 918
      SEQ_LCD_PrintFormattedString("%3d", par_value);
2505 tk 919
    }
920
      } else {
921
    u8 chord_ix = par_value & 0x1f;
922
    u8 chord_char = ((chord_ix >= 0x10) ? 'a' : 'A') + (chord_ix & 0xf);
923
    u8 chord_oct = par_value >> 5;
924
    SEQ_LCD_PrintFormattedString("%c/%d", chord_char, chord_oct);
925
      }
1142 tk 926
      SEQ_LCD_PrintVBar(layer_event.midi_package.velocity >> 4);
927
    } else {
928
      SEQ_LCD_PrintString("----");
929
    }
1143 tk 930
  } break;
1142 tk 931
 
932
  case SEQ_PAR_Type_Length:
933
    SEQ_LCD_PrintGatelength(layer_event.len);
934
    break;
935
 
936
  case SEQ_PAR_Type_CC:
1422 tk 937
  case SEQ_PAR_Type_ProgramChange:
2389 tk 938
  case SEQ_PAR_Type_PitchBend:
939
  case SEQ_PAR_Type_Aftertouch: {
2564 tk 940
    if( !print_without_gate && event_mode == SEQ_EVENT_MODE_CC && !SEQ_TRG_GateGet(track, step, instrument) ) {
1142 tk 941
      SEQ_LCD_PrintString("----");
942
    } else {
2101 tk 943
      //u8 value = (layer_type == SEQ_PAR_Type_ProgramChange) ? layer_event.midi_package.evnt1 : layer_event.midi_package.value;
944
      u8 value = SEQ_PAR_Get(track, step, par_layer, instrument); // works better in drum view
1811 tk 945
      if( value >= 0x80 ) {
2448 tk 946
    SEQ_LCD_PrintFormattedString("----");
1811 tk 947
      } else {
948
    SEQ_LCD_PrintFormattedString("%3d", value);
949
    SEQ_LCD_PrintVBar(value >> 4);
950
      }
1142 tk 951
    }
952
  } break;
953
 
954
  case SEQ_PAR_Type_Probability:
1219 tk 955
    SEQ_LCD_PrintProbability(SEQ_PAR_ProbabilityGet(track, step, instrument, 0x0000));
1142 tk 956
    break;
957
 
958
  case SEQ_PAR_Type_Delay:
1219 tk 959
    SEQ_LCD_PrintStepDelay(SEQ_PAR_StepDelayGet(track, step, instrument, 0x0000));
1142 tk 960
    break;
961
 
962
  case SEQ_PAR_Type_Roll:
1219 tk 963
    SEQ_LCD_PrintRollMode(SEQ_PAR_RollModeGet(track, step, instrument, 0x0000));
1142 tk 964
    break;
965
 
966
  case SEQ_PAR_Type_Roll2:
1219 tk 967
    SEQ_LCD_PrintRoll2Mode(SEQ_PAR_Roll2ModeGet(track, step, instrument, 0x0000));
1142 tk 968
    break;
969
 
2162 tk 970
  case SEQ_PAR_Type_Nth1:
971
    SEQ_LCD_PrintNthValue(SEQ_PAR_Nth1ValueGet(track, step, instrument, 0x0000));
2159 tk 972
    break;
973
 
2162 tk 974
  case SEQ_PAR_Type_Nth2:
975
    SEQ_LCD_PrintNthValue(SEQ_PAR_Nth2ValueGet(track, step, instrument, 0x0000));
976
    break;
977
 
2435 tk 978
  case SEQ_PAR_Type_Root:
979
    SEQ_LCD_PrintRootValue(SEQ_PAR_RootValueGet(track, step, instrument, 0x0000));
980
    break;
981
 
982
  case SEQ_PAR_Type_Scale:
983
    SEQ_LCD_PrintScaleValue(SEQ_PAR_ScaleValueGet(track, step, instrument, 0x0000));
984
    break;
985
 
1142 tk 986
  default:
987
    SEQ_LCD_PrintString("????");
988
    break;
989
  }
990
 
991
  return 0; // no error
992
}
993
 
994
/////////////////////////////////////////////////////////////////////////////
38 tk 995
// prints selected group/track (4 characters)
996
/////////////////////////////////////////////////////////////////////////////
484 tk 997
s32 SEQ_LCD_PrintGxTy(u8 group, u16 selected_tracks)
38 tk 998
{
999
  const char selected_tracks_tab[16] = { '-', '1', '2', 'M', '3', 'M', 'M', 'M', '4', 'M', 'M', 'M', 'M', 'M', 'M', 'A' };
484 tk 1000
  u8 track4 = (selected_tracks >> (group*4)) & 0x0f;
38 tk 1001
 
278 tk 1002
  SEQ_LCD_PrintChar('G');
1003
  SEQ_LCD_PrintChar('1' + group);
1004
  SEQ_LCD_PrintChar('T');
484 tk 1005
  SEQ_LCD_PrintChar(selected_tracks_tab[track4 & 0xf]);
38 tk 1006
 
1007
  return 0; // no error
1008
}
1009
 
184 tk 1010
/////////////////////////////////////////////////////////////////////////////
252 tk 1011
// prints the pattern number (2 characters)
184 tk 1012
/////////////////////////////////////////////////////////////////////////////
1013
s32 SEQ_LCD_PrintPattern(seq_pattern_t pattern)
1014
{
1015
  if( pattern.DISABLED ) {
278 tk 1016
    SEQ_LCD_PrintChar('-');
1017
    SEQ_LCD_PrintChar('-');
184 tk 1018
  } else {
278 tk 1019
    SEQ_LCD_PrintChar('A' + pattern.group + (pattern.lower ? 32 : 0));
1020
    SEQ_LCD_PrintChar('1' + pattern.num);
184 tk 1021
  }
38 tk 1022
 
184 tk 1023
  return 0; // no error
1024
}
1025
 
1026
 
38 tk 1027
/////////////////////////////////////////////////////////////////////////////
316 tk 1028
// prints the pattern label as a 15 character string
1029
// The label is located at character position 5..19 of a pattern name
252 tk 1030
/////////////////////////////////////////////////////////////////////////////
316 tk 1031
s32 SEQ_LCD_PrintPatternLabel(seq_pattern_t pattern, char *pattern_name)
252 tk 1032
{
1033
  // if string only contains spaces, print pattern number instead
1034
  int i;
1035
  u8 found_char = 0;
316 tk 1036
  for(i=5; i<20; ++i)
252 tk 1037
    if( pattern_name[i] != ' ' ) {
1038
      found_char = 1;
1039
      break;
1040
    }
1041
 
1042
  if( found_char )
316 tk 1043
    SEQ_LCD_PrintStringPadded((char *)&pattern_name[5], 15);
252 tk 1044
  else {
278 tk 1045
    SEQ_LCD_PrintString("<Pattern ");
252 tk 1046
    SEQ_LCD_PrintPattern(pattern);
278 tk 1047
    SEQ_LCD_PrintChar('>');
316 tk 1048
    SEQ_LCD_PrintSpaces(3);
252 tk 1049
  }
1050
 
1051
  return 0; // no error
1052
}
1053
 
1054
 
1055
/////////////////////////////////////////////////////////////////////////////
316 tk 1056
// prints the pattern category as a 5 character string
1057
// The category is located at character position 0..4 of a pattern name
252 tk 1058
/////////////////////////////////////////////////////////////////////////////
316 tk 1059
s32 SEQ_LCD_PrintPatternCategory(seq_pattern_t pattern, char *pattern_name)
252 tk 1060
{
316 tk 1061
  // if string only contains spaces, print "NoCat" instead
1062
  int i;
1063
  u8 found_char = 0;
1064
  for(i=0; i<5; ++i)
1065
    if( pattern_name[i] != ' ' ) {
1066
      found_char = 1;
1067
      break;
1068
    }
1069
 
1070
  if( found_char )
1071
    SEQ_LCD_PrintStringPadded((char *)&pattern_name[0], 5);
1072
  else
1073
    SEQ_LCD_PrintString("NoCat");
1074
 
1075
  return 0; // no error
1076
}
1077
 
1078
 
1079
/////////////////////////////////////////////////////////////////////////////
1080
// prints the track label as a 15 character string
1081
// The label is located at character position 5..19 of a track name
1082
/////////////////////////////////////////////////////////////////////////////
1083
s32 SEQ_LCD_PrintTrackLabel(u8 track, char *track_name)
1084
{
252 tk 1085
  // if string only contains spaces, print track number instead
1086
  int i;
1087
  u8 found_char = 0;
316 tk 1088
  for(i=5; i<20; ++i)
252 tk 1089
    if( track_name[i] != ' ' ) {
1090
      found_char = 1;
1091
      break;
1092
    }
1093
 
1094
  if( found_char )
316 tk 1095
    SEQ_LCD_PrintStringPadded((char *)&track_name[5], 15);
252 tk 1096
  else {
326 tk 1097
    // "  USB1 Chn.xx  "
1098
    SEQ_LCD_PrintChar(' ');
1099
    SEQ_LCD_PrintChar(' ');
1100
    SEQ_LCD_PrintMIDIOutPort(SEQ_CC_Get(track, SEQ_CC_MIDI_PORT));
1101
    SEQ_LCD_PrintChar(' ');
1102
    SEQ_LCD_PrintFormattedString("Chn.%2d  ", SEQ_CC_Get(track, SEQ_CC_MIDI_CHANNEL)+1);
252 tk 1103
  }
1104
 
1105
  return 0; // no error
1106
}
1107
 
1108
 
1109
/////////////////////////////////////////////////////////////////////////////
316 tk 1110
// prints the track category as a 5 character string
1111
// The category is located at character position 0..4 of a track name
1112
/////////////////////////////////////////////////////////////////////////////
1113
s32 SEQ_LCD_PrintTrackCategory(u8 track, char *track_name)
1114
{
1115
  // if string only contains spaces, print "NoCat" instead
1116
  int i;
1117
  u8 found_char = 0;
1118
  for(i=0; i<5; ++i)
1119
    if( track_name[i] != ' ' ) {
1120
      found_char = 1;
1121
      break;
1122
    }
1123
 
1124
  if( found_char )
1125
    SEQ_LCD_PrintStringPadded((char *)&track_name[0], 5);
1126
  else
1127
    SEQ_LCD_PrintString("NoCat");
1128
 
1129
  return 0; // no error
1130
}
1131
 
1132
 
1133
/////////////////////////////////////////////////////////////////////////////
319 tk 1134
// prints the drum instrument as a 5 character string
1135
// The drum name is located at character position drum * (0..4) of a track name
1136
/////////////////////////////////////////////////////////////////////////////
1137
s32 SEQ_LCD_PrintTrackDrum(u8 track, u8 drum, char *track_name)
1138
{
1139
  // if string only contains spaces, print "NoCat" instead
1140
  int i;
1141
  u8 found_char = 0;
1142
  for(i=0; i<5; ++i)
1143
    if( track_name[5*drum+i] != ' ' ) {
1144
      found_char = 1;
1145
      break;
1146
    }
1147
 
1148
  if( found_char )
1149
    SEQ_LCD_PrintStringPadded((char *)&track_name[5*drum], 5);
1150
  else {
1151
    SEQ_LCD_PrintFormattedString("Drm%c ", 'A'+drum);
1152
  }
1153
 
1154
  return 0; // no error
1155
}
1156
 
1157
 
1158
/////////////////////////////////////////////////////////////////////////////
285 tk 1159
// prints MIDI In port (4 characters)
38 tk 1160
/////////////////////////////////////////////////////////////////////////////
285 tk 1161
s32 SEQ_LCD_PrintMIDIInPort(mios32_midi_port_t port)
38 tk 1162
{
285 tk 1163
  return SEQ_LCD_PrintString(SEQ_MIDI_PORT_InNameGet(SEQ_MIDI_PORT_InIxGet(port)));
38 tk 1164
 
1165
  return 0; // no error
1166
}
1167
 
1168
 
1169
/////////////////////////////////////////////////////////////////////////////
285 tk 1170
// prints MIDI Out port (4 characters)
1171
/////////////////////////////////////////////////////////////////////////////
1172
s32 SEQ_LCD_PrintMIDIOutPort(mios32_midi_port_t port)
1173
{
1174
  return SEQ_LCD_PrintString(SEQ_MIDI_PORT_OutNameGet(SEQ_MIDI_PORT_OutIxGet(port)));
1175
 
1176
  return 0; // no error
1177
}
1178
 
1179
 
1180
/////////////////////////////////////////////////////////////////////////////
38 tk 1181
// prints step view (6 characters)
1182
/////////////////////////////////////////////////////////////////////////////
1183
s32 SEQ_LCD_PrintStepView(u8 step_view)
1184
{
1185
 
278 tk 1186
  SEQ_LCD_PrintFormattedString("S%2d-%2d", (step_view*16)+1, (step_view+1)*16);
38 tk 1187
 
1188
  return 0; // no error
1189
}
744 tk 1190
 
1191
 
1192
/////////////////////////////////////////////////////////////////////////////
1193
// Help function to print a list (e.g. directory)
1194
// Each item has 9 characters maximum (no termination required if 9 chars)
1195
// Prints item_width * num_items + (num_items-1) characters
1196
// (last space is left out so that arrows can be displayed at the end of list)
1197
// *list: pointer to list array
1198
// item_width: maximum width of item (defines also the string length!)
1199
// max_items_on_screen: how many items are displayed on screen?
1200
//
749 tk 1201
// A space is added at the end of each item. The last item gets
1202
// a page scroll marker (< or > or <>)
744 tk 1203
/////////////////////////////////////////////////////////////////////////////
749 tk 1204
s32 SEQ_LCD_PrintList(char *list, u8 item_width, u8 num_items, u8 max_items_on_screen, u8 selected_item_on_screen, u8 view_offset)
744 tk 1205
{
1206
  int item;
1207
 
1208
  for(item=0; item<max_items_on_screen; ++item) {
1209
    char *list_item = (char *)&list[item*item_width];
1210
    int len, pos;
1211
 
1212
    for(len=0; len<item_width; ++len)
1213
      if( list_item[len] == 0 )
1214
    break;
1215
 
749 tk 1216
    if( item == selected_item_on_screen && ui_cursor_flash )
1217
      SEQ_LCD_PrintSpaces(item_width);
1218
    else {
1219
      int centered_offset = ((item_width+1)-len)/2;
744 tk 1220
 
749 tk 1221
      if( centered_offset )
1222
    SEQ_LCD_PrintSpaces(centered_offset);
744 tk 1223
 
749 tk 1224
      for(pos=0; pos<len; ++pos)
1225
    SEQ_LCD_PrintChar(list_item[pos]);
744 tk 1226
 
749 tk 1227
      centered_offset = item_width-centered_offset-len;
1228
      if( centered_offset > 0 )
1229
    SEQ_LCD_PrintSpaces(centered_offset);
1230
    }
744 tk 1231
 
1232
    if( item < (max_items_on_screen-1) )
1233
      SEQ_LCD_PrintChar(' ');
749 tk 1234
    else {
1235
      if( view_offset == 0 && selected_item_on_screen == 0 )
1236
    SEQ_LCD_PrintChar(0x01); // right arrow
1237
      else if( (view_offset+selected_item_on_screen+1) >= num_items )
1238
    SEQ_LCD_PrintChar(0x00); // left arrow
1239
      else
1240
    SEQ_LCD_PrintChar(0x02); // left/right arrow
1241
    }
744 tk 1242
  }
1243
 
1244
  return 0; // no error
1245
}