Subversion Repositories svn.mios32

Rev

Rev 2414 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2414 pcbatterij 1
// $Id: seq_terminal.c 2176 2015-05-17 16:32:08Z tk $
2
/*
3
 * MIDIbox SEQ MIDI Terminal
4
 *
5
 * ==========================================================================
6
 *
7
 *  Copyright (C) 2010 Thorsten Klose (tk@midibox.org)
8
 *  Licensed for personal non-commercial use only.
9
 *  All other rights reserved.
10
 *
11
 * ==========================================================================
12
 */
13
 
14
/////////////////////////////////////////////////////////////////////////////
15
// Include files
16
/////////////////////////////////////////////////////////////////////////////
17
 
18
#include <mios32.h>
19
#include <string.h>
20
 
21
#include <seq_midi_out.h>
22
#include <ff.h>
23
 
24
#include <aout.h>
25
#include <app_lcd.h>
26
 
27
#include "tasks.h"
28
 
29
#include "app.h"
30
#include "seq_terminal.h"
31
 
32
 
33
#include "seq_core.h"
34
#include "seq_cc.h"
35
#include "seq_layer.h"
36
#include "seq_par.h"
37
#include "seq_trg.h"
38
#include "seq_record.h"
39
#include "seq_midi_port.h"
40
#include "seq_midi_router.h"
41
#include "seq_blm.h"
42
#include "seq_song.h"
43
#include "seq_mixer.h"
44
#include "seq_hwcfg.h"
45
#include "seq_tpd.h"
46
#include "seq_lcd_logo.h"
47
 
48
#include "file.h"
49
#include "seq_file.h"
50
#include "seq_file_b.h"
51
#include "seq_file_s.h"
52
#include "seq_file_m.h"
53
#include "seq_file_g.h"
54
#include "seq_file_c.h"
55
#include "seq_file_t.h"
56
#include "seq_file_gc.h"
57
#include "seq_file_bm.h"
58
#include "seq_file_hw.h"
59
 
60
#include "seq_ui.h"
61
 
62
#include "seq_statistics.h"
63
 
64
#if !defined(MIOS32_FAMILY_EMULATION)
65
#include "uip_terminal.h"
2434 tk 66
 
67
extern void vPortMallocDebugInfo(void);
2414 pcbatterij 68
#endif
69
 
70
 
71
/////////////////////////////////////////////////////////////////////////////
72
// Local defines
73
/////////////////////////////////////////////////////////////////////////////
74
 
75
#define STRING_MAX 100 // recommended size for file transfers via FILE_BrowserHandler()
76
 
77
 
78
/////////////////////////////////////////////////////////////////////////////
79
// Local variables
80
/////////////////////////////////////////////////////////////////////////////
81
 
82
static char line_buffer[STRING_MAX];
83
static u16 line_ix;
84
 
85
typedef enum {
86
  UPLOADING_FILE_NONE,
87
  UPLOADING_FILE_HW,
88
  UPLOADING_FILE_C,
89
  UPLOADING_FILE_GC,
90
  UPLOADING_FILE_G,
91
  UPLOADING_FILE_BM,
92
} uploading_file_t;
93
 
94
static uploading_file_t uploading_file;
95
 
96
/////////////////////////////////////////////////////////////////////////////
97
// Local prototypes
98
/////////////////////////////////////////////////////////////////////////////
99
 
100
static s32 TERMINAL_ParseFilebrowser(mios32_midi_port_t port, char byte);
101
 
102
static s32 TERMINAL_BrowserUploadCallback(char *filename);
103
 
104
 
105
/////////////////////////////////////////////////////////////////////////////
106
// Initialisation
107
/////////////////////////////////////////////////////////////////////////////
108
s32 SEQ_TERMINAL_Init(u32 mode)
109
{
110
  // install the callback function which is called on incoming characters from MIOS Terminal
111
  MIOS32_MIDI_DebugCommandCallback_Init(SEQ_TERMINAL_Parse);
112
 
113
  // install the callback function which is called on incoming characters from MIOS Filebrowser
114
  MIOS32_MIDI_FilebrowserCommandCallback_Init(TERMINAL_ParseFilebrowser);
115
 
116
  // clear line buffer
117
  line_buffer[0] = 0;
118
  line_ix = 0;
119
 
120
  // for file autoload
121
  uploading_file = 0;
122
 
123
  return 0; // no error
124
}
125
 
126
 
127
/////////////////////////////////////////////////////////////////////////////
128
// help function which parses a decimal or hex value
129
// returns >= 0 if value is valid
130
// returns -1 if value is invalid
131
/////////////////////////////////////////////////////////////////////////////
132
static s32 get_dec(char *word)
133
{
134
  if( word == NULL )
135
    return -1;
136
 
137
  char *next;
138
  long l = strtol(word, &next, 0);
139
 
140
  if( word == next )
141
    return -1;
142
 
143
  return l; // value is valid
144
}
145
 
146
 
147
/////////////////////////////////////////////////////////////////////////////
148
// help function which parses for on or off
149
// returns 0 if 'off', 1 if 'on', -1 if invalid
150
/////////////////////////////////////////////////////////////////////////////
151
static s32 get_on_off(char *word)
152
{
153
  if( strcmp(word, "on") == 0 )
154
    return 1;
155
 
156
  if( strcmp(word, "off") == 0 )
157
    return 0;
158
 
159
  return -1;
160
}
161
 
162
 
163
/////////////////////////////////////////////////////////////////////////////
164
// Parser
165
/////////////////////////////////////////////////////////////////////////////
166
s32 SEQ_TERMINAL_Parse(mios32_midi_port_t port, char byte)
167
{
168
  // temporary change debug port (will be restored at the end of this function)
169
  mios32_midi_port_t prev_debug_port = MIOS32_MIDI_DebugPortGet();
170
  MIOS32_MIDI_DebugPortSet(port);
171
 
172
  if( byte == '\r' ) {
173
    // ignore
174
  } else if( byte == '\n' ) {
175
    SEQ_TERMINAL_ParseLine(line_buffer, APP_SendDebugMessage);
176
    line_ix = 0;
177
    line_buffer[line_ix] = 0;
178
  } else if( line_ix < (STRING_MAX-1) ) {
179
    line_buffer[line_ix++] = byte;
180
    line_buffer[line_ix] = 0;
181
  }
182
 
183
  // restore debug port
184
  MIOS32_MIDI_DebugPortSet(prev_debug_port);
185
 
186
  return 0; // no error
187
}
188
 
189
 
190
/////////////////////////////////////////////////////////////////////////////
191
// Parser for Filebrowser
192
/////////////////////////////////////////////////////////////////////////////
193
s32 TERMINAL_ParseFilebrowser(mios32_midi_port_t port, char byte)
194
{
195
  if( byte == '\r' ) {
196
    // ignore
197
  } else if( byte == '\n' ) {
198
    // for the auto-load function
199
    FILE_BrowserUploadCallback_Init(TERMINAL_BrowserUploadCallback);
200
 
201
    MUTEX_MIDIOUT_TAKE;
202
    MUTEX_SDCARD_TAKE;
203
    FILE_BrowserHandler(port, line_buffer);
204
    MUTEX_SDCARD_GIVE;
205
    MUTEX_MIDIOUT_GIVE;
206
    line_ix = 0;
207
    line_buffer[line_ix] = 0;
208
  } else if( line_ix < (STRING_MAX-1) ) {
209
    line_buffer[line_ix++] = byte;
210
    line_buffer[line_ix] = 0;
211
  }
212
 
213
  return 0; // no error
214
}
215
 
216
/////////////////////////////////////////////////////////////////////////////
217
//! For the auto-load function
218
/////////////////////////////////////////////////////////////////////////////
219
static s32 TERMINAL_BrowserUploadCallback(char *filename)
220
{
221
  if( filename ) {
222
    // check for MBSEQ_HW.V4
223
    uploading_file = UPLOADING_FILE_NONE;
224
    if( strcasecmp(filename, "/mbseq_hw.v4") == 0 )
225
      uploading_file = UPLOADING_FILE_HW;
226
    else if( strcasestr(filename, "/mbseq_c.v4") != NULL )
227
      uploading_file = UPLOADING_FILE_C;
228
    else if( strcasecmp(filename, "/mbseq_gc.v4") == 0 )
229
      uploading_file = UPLOADING_FILE_GC;
230
    else if( strcasestr(filename, "/mbseq_g.v4") != NULL )
231
      uploading_file = UPLOADING_FILE_G;
232
    else if( strcasestr(filename, "/mbseq_bm.v4") != NULL )
233
      uploading_file = UPLOADING_FILE_BM;
234
  } else {
235
    switch( uploading_file ) {
236
 
237
    case UPLOADING_FILE_HW: {
238
      DEBUG_MSG("AUTOLOAD '/MBSEQ_HW.V4'\n");
239
      SEQ_HWCFG_Init(0);
240
      SEQ_FILE_HW_Init(0);
241
      SEQ_FILE_HW_Load();      
242
    } break;
243
 
244
    case UPLOADING_FILE_C: {
245
      DEBUG_MSG("AUTOLOAD 'MBSEQ_C.V4'\n");
246
      SEQ_FILE_C_Load(seq_file_session_name);
247
    } break;
248
 
249
    case UPLOADING_FILE_GC: {
250
      DEBUG_MSG("AUTOLOAD '/MBSEQ_GC.V4'\n");
251
      SEQ_FILE_GC_Load();
252
    } break;
253
 
254
    case UPLOADING_FILE_G: {
255
      DEBUG_MSG("AUTOLOAD 'MBSEQ_G.V4'\n");
256
      SEQ_FILE_G_Load(seq_file_session_name);
257
    } break;
258
 
259
    case UPLOADING_FILE_BM: {
260
      DEBUG_MSG("AUTOLOAD 'MBSEQ_BM.V4'\n");
261
      SEQ_FILE_BM_Load(seq_file_session_name, 1); // global
262
      SEQ_FILE_BM_Load(seq_file_session_name, 0); // session
263
    } break;
264
 
265
 
266
    }
267
  }
268
 
269
  return 0; // no error
270
}
271
 
272
/////////////////////////////////////////////////////////////////////////////
273
// Parser for a complete line - also used by shell.c for telnet
274
/////////////////////////////////////////////////////////////////////////////
275
s32 SEQ_TERMINAL_ParseLine(char *input, void *_output_function)
276
{
277
  void (*out)(char *format, ...) = _output_function;
278
  char *separators = " \t";
279
  char *brkt;
280
  char *parameter;
281
 
282
  MUTEX_MIDIOUT_TAKE;
283
 
284
#if !defined(MIOS32_FAMILY_EMULATION)
285
  if( UIP_TERMINAL_ParseLine(input, _output_function) >= 1 )
286
    return 0; // command parsed by UIP Terminal
287
#endif
288
 
289
#if !defined(MIOS32_FAMILY_EMULATION)
290
  if( AOUT_TerminalParseLine(input, _output_function) >= 1 )
291
    return 0; // command parsed
292
#endif
293
 
294
#ifdef MIOS32_LCD_universal
295
  if( APP_LCD_TerminalParseLine(input, _output_function) >= 1 )
296
    return 0; // command parsed
297
#endif
298
 
299
  MUTEX_MIDIOUT_GIVE;
300
 
301
  if( (parameter = strtok_r(line_buffer, separators, &brkt)) ) {
302
    if( strcmp(parameter, "help") == 0 ) {
303
      SEQ_TERMINAL_PrintHelp(out);
304
    } else if( strcmp(parameter, "system") == 0 ) {
305
      SEQ_TERMINAL_PrintSystem(out);
306
    } else if( strcmp(parameter, "memory") == 0 ) {
307
      SEQ_TERMINAL_PrintMemoryInfo(out);
308
    } else if( strcmp(parameter, "sdcard") == 0 ) {
309
      SEQ_TERMINAL_PrintSdCardInfo(out);
310
    } else if( strcmp(parameter, "sdcard_format") == 0 ) {
311
      if( !brkt || strcasecmp(brkt, "yes, I'm sure") != 0 ) {
312
    out("ATTENTION: this command will format your SD Card!!!");
313
    out("           ALL DATA WILL BE DELETED FOREVER!!!");
314
    out("           Check the current content with the 'sdcard' command");
315
    out("           Create a backup on your computer if necessary!");
316
    out("To start formatting, please enter: sdcard_format yes, I'm sure");
317
    if( brkt ) {
318
      out("('%s' wasn't the right \"password\")", brkt);
319
    }
320
      } else {
321
#if !defined(MIOS32_FAMILY_EMULATION)
322
    MUTEX_SDCARD_TAKE;
323
    out("Formatting SD Card...");
324
    FRESULT res;
325
    if( (res=f_mkfs(0,0,0)) != FR_OK ) {
326
      out("Formatting failed with error code: %d!", res);
327
    } else {
328
      out("...with success!");
329
#ifdef MBSEQV4L    
330
      out("Please upload your MBSEQ_HW.V4L file with the MIOS Filebrowser now!");
331
#else
332
      out("Please upload your MBSEQ_HW.V4 file with the MIOS Filebrowser now!");
333
#endif
334
      out("Thereafter enter 'reset' to restart the application.");
335
    }
336
    MUTEX_SDCARD_GIVE;
337
#else
338
    out("Not in emulation...!");
339
#endif
340
      }
341
    } else if( strcmp(parameter, "global") == 0 ) {
342
      SEQ_TERMINAL_PrintGlobalConfig(out);
343
    } else if( strcmp(parameter, "bookmarks") == 0 ) {
344
      SEQ_TERMINAL_PrintBookmarks(out);
345
    } else if( strcmp(parameter, "config") == 0 ) {
346
      SEQ_TERMINAL_PrintSessionConfig(out);
347
    } else if( strcmp(parameter, "tracks") == 0 ) {
348
      SEQ_TERMINAL_PrintTracks(out);
349
    } else if( strcmp(parameter, "track") == 0 ) {
350
      char *arg;
351
      if( (arg = strtok_r(NULL, separators, &brkt)) ) {
352
    int track = get_dec(arg);
353
    if( track < 1 || track > SEQ_CORE_NUM_TRACKS ) {
354
      out("Wrong track number %d - expected track 1..%d\n", track, SEQ_CORE_NUM_TRACKS);
355
    } else {
356
      SEQ_TERMINAL_PrintTrack(out, track-1);
357
    }
358
      } else {
359
    out("Please specify track, e.g. \"track 1\"");
360
      }
361
    } else if( strcmp(parameter, "mixer") == 0 ) {
362
      SEQ_TERMINAL_PrintCurrentMixerMap(out);
363
    } else if( strcmp(parameter, "song") == 0 ) {
364
      SEQ_TERMINAL_PrintCurrentSong(out);
365
    } else if( strcmp(parameter, "grooves") == 0 ) {
366
      SEQ_TERMINAL_PrintGrooveTemplates(out);
367
    } else if( strcmp(parameter, "msd") == 0 ) {
368
      out("Mass Storage Device Mode not supported by this application!");
369
    } else if( strcmp(parameter, "tpd") == 0 ) {
370
      SEQ_TPD_PrintString(brkt); // easter egg ;-)
371
    } else if( strcmp(parameter, "set") == 0 ) {
372
      if( (parameter = strtok_r(NULL, separators, &brkt)) ) {
373
    if( strcmp(parameter, "router") == 0 ) {
374
      char *arg;
375
      if( !(arg = strtok_r(NULL, separators, &brkt)) ) {
376
        out("Missing node number!");
377
      } else {
378
        s32 node = get_dec(arg);
379
        if( node < 1 || node > SEQ_MIDI_ROUTER_NUM_NODES ) {
380
          out("Expecting node number between 1..%d!", SEQ_MIDI_ROUTER_NUM_NODES);
381
        } else {
382
          node-=1; // user counts from 1
383
 
384
          if( !(arg = strtok_r(NULL, separators, &brkt)) ) {
385
        out("Missing input port!");
386
          } else {
387
        mios32_midi_port_t src_port = 0xff;
388
        int port_ix;
389
        for(port_ix=0; port_ix<SEQ_MIDI_PORT_InNumGet(); ++port_ix) {
390
          // terminate port name at first space
391
          char port_name[10];
392
          strcpy(port_name, SEQ_MIDI_PORT_InNameGet(port_ix));
393
          int i; for(i=0; i<strlen(port_name); ++i) if( port_name[i] == ' ' ) port_name[i] = 0;
394
 
395
          if( strcmp(arg, port_name) == 0 ) {
396
            src_port = SEQ_MIDI_PORT_InPortGet(port_ix);
397
            break;
398
          }
399
        }
400
 
401
        if( src_port >= 0xf0 ) {
402
          out("Unknown or invalid MIDI input port!");
403
        } else {
404
 
405
          char *arg_src_chn;
406
          if( !(arg_src_chn = strtok_r(NULL, separators, &brkt)) ) {
407
            out("Missing source channel, expecting off, 1..16 or all!");
408
          } else {
409
            int src_chn = -1;
410
 
411
            if( strcmp(arg_src_chn, "---") == 0 || strcmp(arg_src_chn, "off") == 0 )
412
              src_chn = 0;
413
            else if( strcasecmp(arg_src_chn, "all") == 0 )
414
              src_chn = 17;
415
            else {
416
              src_chn = get_dec(arg_src_chn);
417
              if( src_chn > 16 )
418
            src_chn = -1;
419
            }
420
 
421
            if( src_chn < 0 ) {
422
              out("Invalid source channel, expecting off, 1..16 or all!");
423
            } else {
424
 
425
              if( !(arg = strtok_r(NULL, separators, &brkt)) ) {
426
            out("Missing output port!");
427
              } else {
428
            mios32_midi_port_t dst_port = 0xff;
429
            int port_ix;
430
            for(port_ix=0; port_ix<SEQ_MIDI_PORT_OutNumGet(); ++port_ix) {
431
              // terminate port name at first space
432
              char port_name[10];
433
              strcpy(port_name, SEQ_MIDI_PORT_OutNameGet(port_ix));
434
              int i; for(i=0; i<strlen(port_name); ++i) if( port_name[i] == ' ' ) port_name[i] = 0;
435
 
436
              if( strcmp(arg, port_name) == 0 ) {
437
                dst_port = SEQ_MIDI_PORT_OutPortGet(port_ix);
438
                break;
439
              }
440
            }
441
 
442
            if( dst_port >= 0xf0 ) {
443
              out("Unknown or invalid MIDI output port!");
444
            } else {
445
 
446
              char *arg_dst_chn;
447
              if( !(arg_dst_chn = strtok_r(NULL, separators, &brkt)) ) {
448
                out("Missing destination channel, expecting off, 1..16 or all!");
449
              } else {
450
                int dst_chn = -1;
451
 
452
                if( strcmp(arg_dst_chn, "---") == 0 || strcmp(arg_dst_chn, "off") == 0 )
453
                  dst_chn = 0;
454
                else if( strcasecmp(arg_dst_chn, "all") == 0 )
455
                  dst_chn = 17;
456
                else if( strcasecmp(arg_dst_chn, "trk") == 0 || strcasecmp(arg_dst_chn, "track") == 0 )
457
                  dst_chn = 18;
458
                else if( strcasecmp(arg_dst_chn, "stk") == 0 ||
459
                     strcasecmp(arg_dst_chn, "strk") == 0 ||
460
                     strcasecmp(arg_dst_chn, "seltrk") == 0 ||
461
                     strcasecmp(arg_dst_chn, "seltrack") == 0 ||
462
                     strcasecmp(arg_dst_chn, "track") == 0 )
463
                  dst_chn = 19;
464
                else {
465
                  dst_chn = get_dec(arg_dst_chn);
466
                  if( dst_chn > 16 )
467
                dst_chn = -1;
468
                }
469
 
470
                if( dst_chn < 0 ) {
471
                  out("Invalid destination channel, expecting off, 1..16 or all!");
472
                } else {
473
                  //
474
                  // finally...
475
                  //
476
                  seq_midi_router_node_t *n = &seq_midi_router_node[node];
477
                  n->src_port = src_port;
478
                  n->src_chn = src_chn;
479
                  n->dst_port = dst_port;
480
                  n->dst_chn = dst_chn;
481
 
482
                  out("Changed Node %d to SRC:%s %s  DST:%s %s",
483
                  node+1,
484
                  SEQ_MIDI_PORT_InNameGet(SEQ_MIDI_PORT_InIxGet(n->src_port)),
485
                  arg_src_chn,
486
                  SEQ_MIDI_PORT_OutNameGet(SEQ_MIDI_PORT_OutIxGet(n->dst_port)),
487
                  arg_dst_chn);
488
                }
489
              }
490
            }
491
              }
492
            }
493
          }
494
        }
495
          }
496
        }
497
      }
498
    } else if( strcmp(parameter, "mclk_in") == 0 || strcmp(parameter, "mclk_out") == 0 ) {
499
      int mclk_in = strcmp(parameter, "mclk_in") == 0;
500
 
501
      char *arg;
502
      if( !(arg = strtok_r(NULL, separators, &brkt)) ) {
503
        out("Missing MIDI clock port!");
504
      } else {
505
        mios32_midi_port_t mclk_port = 0xff;
506
        int port_ix;
507
        for(port_ix=0; port_ix<SEQ_MIDI_PORT_ClkNumGet(); ++port_ix) {
508
          // terminate port name at first space
509
          char port_name[10];
510
          strcpy(port_name, SEQ_MIDI_PORT_ClkNameGet(port_ix));
511
          int i; for(i=0; i<strlen(port_name); ++i) if( port_name[i] == ' ' ) port_name[i] = 0;
512
 
513
          if( strcmp(arg, port_name) == 0 ) {
514
        mclk_port = SEQ_MIDI_PORT_ClkPortGet(port_ix);
515
        break;
516
          }
517
        }
518
 
519
        if( mclk_in && mclk_port >= 0xf0 ) {
520
          // extra: allow 'INx' as well
521
          if( strncmp(arg, "IN", 2) == 0 && arg[2] >= '1' && arg[2] <= '4' )
522
        mclk_port = UART0 + (arg[2] - '1');
523
        }
524
 
525
        if( !mclk_in && mclk_port >= 0xf0 ) {
526
          // extra: allow 'OUTx' as well
527
          if( strncmp(arg, "OUT", 3) == 0 && arg[3] >= '1' && arg[3] <= '4' )
528
        mclk_port = UART0 + (arg[3] - '1');
529
        }
530
 
531
        if( mclk_port >= 0xf0 ) {
532
          out("Unknown or invalid MIDI Clock port!");
533
        } else {
534
          int on_off = -1;
535
          char *arg_on_off;
536
          if( !(arg_on_off = strtok_r(NULL, separators, &brkt)) ||
537
          (on_off = get_on_off(arg_on_off)) < 0 ) {
538
        out("Missing 'on' or 'off' after port name!");
539
          } else {
540
        if( mclk_in ) {
541
          if( SEQ_MIDI_ROUTER_MIDIClockInSet(mclk_port, on_off) < 0 )
542
            out("Failed to set MIDI Clock port %s", arg);
543
          else
544
            out("Set MIDI Clock for IN port %s to %s\n", arg, arg_on_off);
545
        } else {
546
          if( SEQ_MIDI_ROUTER_MIDIClockOutSet(mclk_port, on_off) < 0 )
547
            out("Failed to set MIDI Clock port %s", arg);
548
          else
549
            out("Set MIDI Clock for OUT port %s to %s\n", arg, arg_on_off);
550
        }
551
          }
552
        }
553
      }
554
    } else if( strcmp(parameter, "din_testmode") == 0 ) {
555
          int on_off = -1;
556
          if( (parameter = strtok_r(NULL, separators, &brkt)) )
557
            on_off = get_on_off(parameter);
558
 
559
          if( on_off < 0 ) {
560
            out("Expecting 'on' or 'off'");
561
          } else {
562
            app_din_testmode = on_off;
563
            out("DIN testmode turned %s", on_off ? "on" : "off");
564
          }
565
    } else if( strcmp(parameter, "blm_port") == 0 ) {
566
      char *arg;
567
      if( !(arg = strtok_r(NULL, separators, &brkt)) ) {
568
        out("Please specifify BLM MIDI input port or 'off' to disable BLM!");
569
      } else {
570
        if( strcmp(arg, "off") == 0 ) {
571
          seq_blm_port = 0x00;
572
          out("BLM port has been disabled!");
573
        } else {
574
          mios32_midi_port_t blm_port = 0xff;
575
          int port_ix;
576
          for(port_ix=0; port_ix<SEQ_MIDI_PORT_InNumGet(); ++port_ix) {
577
        // terminate port name at first space
578
        char port_name[10];
579
        strcpy(port_name, SEQ_MIDI_PORT_InNameGet(port_ix));
580
        int i; for(i=0; i<strlen(port_name); ++i) if( port_name[i] == ' ' ) port_name[i] = 0;
581
 
582
        if( strcmp(arg, port_name) == 0 ) {
583
          blm_port = SEQ_MIDI_PORT_InPortGet(port_ix);
584
          break;
585
        }
586
          }
587
 
588
          if( blm_port >= 0xf0 ) {
589
        out("Unknown or invalid BLM input port!");
590
          } else {
591
        seq_blm_port = blm_port;
592
        out("BLM port set to %s", SEQ_MIDI_PORT_InNameGet(SEQ_MIDI_PORT_InIxGet(seq_blm_port)));
593
          }
594
        }
595
      }
596
 
597
    } else if( strcmp(parameter, "rec_quantisation") == 0 ) {
598
      char *arg;
599
      int value;
600
      if( !(arg = strtok_r(NULL, separators, &brkt)) ) {
601
        out("Please specify quantisation between 1%%..100%% (default: 10%%, current: %d%%)\n", seq_record_quantize);
602
      } else {
603
        int len;
604
        while( (len=strlen(arg)) && arg[len-1] == '%' ) {
605
          arg[len-1] = 0;
606
        }
607
 
608
        if( (value=get_dec(arg)) < 0 || value > 100 ) {
609
          out("Quantisation should be between 1%%..100%%!");
610
        } else {
611
          seq_record_quantize = value;
612
          out("Quantisation set to %d%%\n", seq_record_quantize);
613
          out("Enter 'store' to save this setting on SD Card.");
614
        }
615
      }
616
    } else {
617
      out("Unknown set parameter: '%s'!", parameter);
618
    }
619
      } else {
620
    out("Missing parameter after 'set'!");
621
      }
622
    } else if( strcmp(parameter, "router") == 0 ) {
623
      SEQ_TERMINAL_PrintRouterInfo(out);
624
    } else if( strcmp(parameter, "play") == 0 || strcmp(parameter, "start") == 0 ) { // play or start do the same
625
      SEQ_UI_Button_Play(0);
626
      out("Sequencer started...");
627
    } else if( strcmp(parameter, "stop") == 0 ) {
628
      SEQ_UI_Button_Stop(0);
629
      out("Sequencer stopped...");
630
    } else if( strcmp(parameter, "store") == 0 || (strcmp(parameter, "save") == 0 && strlen(brkt) == 0) ) {
631
      if( seq_ui_backup_req || seq_ui_format_req ) {
632
    out("Ongoing session creation - please wait!");
633
      } else if( strlen(brkt) ) {
634
    out("ERROR: use 'save' if you want to store the session under a new name!");
635
      } else {
636
    seq_ui_saveall_req = 1;
637
    out("Storing complete session on SD Card: /SESSIONS/%s\n", seq_file_session_name);
638
      }
639
    } else if( strcmp(parameter, "new") == 0 || strcmp(parameter, "saveas") == 0 || strcmp(parameter, "save") == 0 ) {
640
      if( seq_ui_backup_req || seq_ui_format_req ) {
641
    out("Ongoing session creation - please wait!");
642
      } else {
643
    MUTEX_SDCARD_TAKE;
644
 
645
    char *session_dir = brkt;
646
    u8 new_session = strcmp(parameter, "new") == 0;
647
 
648
    if( !strlen(session_dir) ) {
649
      out("Please specifiy a session name!");
650
    } else {
651
      if( strlen(session_dir) > 8 ) {
652
        out("Session name '%s' too long, only 8 characters allowed!\n", session_dir);
653
      } else if( SEQ_FILE_IsValidSessionName(session_dir) < 1 ) {
654
        out("Session name '%s' contains invalid characters!!\n", session_dir);
655
      } else {
656
        s32 status;
657
        char path[30];
658
        sprintf(path, "%s/%s", SEQ_FILE_SESSION_PATH, session_dir);
659
        status = FILE_DirExists(path);
660
        if( status < 0 ) {
661
          out("SD Card Error %d (FatFs: D%3d)\n", status, file_dfs_errno);
662
        } else if( status >= 1 ) {
663
          out("The session '%s' already exists, please delete it first!\n", session_dir);
664
        } else if( !new_session && SEQ_FILE_SaveAllFiles() < 0 ) {
665
          out("Failed to store session on SD Card: /SESSIONS/%s\n", seq_file_session_name);
666
        } else {
667
          FILE_MakeDir(path); // create directory
668
          status = FILE_DirExists(path);
669
          if( status < 1 ) {
670
        out("Failed to create new session (Error code %d, FatFs: D%3d)\n", status, file_dfs_errno);
671
          } else {
672
        if( (status=SEQ_FILE_CreateSession(session_dir, new_session)) < 0 ) {
673
          out("Failed to create new session during final call (Error code %d, FatFs: D%3d)\n", status, file_dfs_errno);
674
        } else {
675
          if( new_session ) {
676
            out("Creating new session '%s' - please wait, this can take a while!!!\n", session_dir);
677
          } else {
678
            out("Copy current session to '%s' - please wait, this can take a while!!!\n", session_dir);
679
          }
680
        }
681
          }
682
        }
683
      }
684
    }
685
 
686
    MUTEX_SDCARD_GIVE;
687
      }
688
    } else if( strcmp(parameter, "open") == 0 || strcmp(parameter, "load") == 0 ) {
689
      if( seq_ui_backup_req || seq_ui_format_req ) {
690
    out("Ongoing session creation - please wait!");
691
      } else {
692
    MUTEX_SDCARD_TAKE;
693
    char *session_dir = brkt;
694
 
695
    if( !strlen(session_dir) ) {
696
      out("Please specifiy a session name!");
697
    } else {
698
      char path[30];
699
      sprintf(path, "%s/%s", SEQ_FILE_SESSION_PATH, session_dir);
700
 
701
      s32 status = FILE_DirExists(path);
702
      if( status < 0 ) {
703
        out("SD Card Error %d (FatFs: D%3d)\n", status, file_dfs_errno);
704
      } else if( status < 1 ) {
705
        out("The session '%s' doesn't exist!\n", session_dir);
706
      } else {
707
        // remember previous session and switch to new name
708
        char prev_session_name[13];
709
        strcpy(prev_session_name, seq_file_session_name);
710
        strcpy(seq_file_session_name, session_dir);
711
 
712
        // try to load files
713
        status = SEQ_FILE_LoadAllFiles(0); // excluding HW config
714
 
715
        if( status < 0 ) {
716
          // session invalid - switch back to previous one!
717
          strcpy(seq_file_session_name, prev_session_name);
718
          out("The session '%s' is invalid!\n", session_dir);
719
        } else {
720
          out("Changed to session '%s'\n", session_dir);
721
 
722
          // store session name
723
          status |= SEQ_FILE_StoreSessionName();
724
        }
725
      }
726
    }
727
    MUTEX_SDCARD_GIVE;
728
      }
729
    } else if( strcmp(parameter, "delete") == 0 ) {
730
      if( seq_ui_backup_req || seq_ui_format_req ) {
731
    out("Ongoing session creation - please wait!");
732
      } else {
733
    MUTEX_SDCARD_TAKE;
734
    char *session_dir = brkt;
735
 
736
    if( !strlen(session_dir) ) {
737
      out("Please specifiy a session name!");
738
    } else {
739
      char path[30];
740
      sprintf(path, "%s/%s", SEQ_FILE_SESSION_PATH, session_dir);
741
 
742
      s32 status = FILE_DirExists(path);
743
      if( status < 0 ) {
744
        out("SD Card Error %d (FatFs: D%3d)\n", status, file_dfs_errno);
745
      } else if( status < 1 ) {
746
        out("The session '%s' doesn't exist!\n", session_dir);
747
      } else if( strcasecmp(session_dir, seq_file_session_name) == 0 ) {
748
        out("This is the active session! It can't be deleted!");
749
      } else if( strcasecmp(session_dir, "default") == 0 ) {
750
        out("The default session can't be deleted!");
751
      } else if( (status=SEQ_FILE_DeleteSession(session_dir)) < 0 ) {
752
        out("ERROR: delete %s failed!\n", session_dir);
753
      }
754
    }
755
    MUTEX_SDCARD_GIVE;
756
      }
757
    } else if( strcmp(parameter, "session") == 0 ) {
758
      out("Current session: %s", seq_file_session_name);
759
    } else if( strcmp(parameter, "sessions") == 0 ) {
760
      if( seq_ui_backup_req || seq_ui_format_req ) {
761
    out("Ongoing session creation - please wait!");
762
      } else {
763
    MUTEX_SDCARD_TAKE;
764
    s32 status = 0;
765
    DIR di;
766
    FILINFO de;
767
 
768
    if( f_opendir(&di, SEQ_FILE_SESSION_PATH) != FR_OK ) {
769
      out("ERROR: the %s directory doesn't exist!", SEQ_FILE_SESSION_PATH);
770
    } else {
771
      int num_dirs = 0;
772
      while( status == 0 && f_readdir(&di, &de) == FR_OK && de.fname[0] != 0 ) {
773
        if( de.fname[0] && de.fname[0] != '.' && (de.fattrib & AM_DIR) && !(de.fattrib & AM_HID) ) {
774
          ++num_dirs;
775
 
776
          out("Session #%3d: %s", num_dirs, de.fname);
777
        }
778
      }
779
      if( num_dirs < 1 ) {
780
        out("No session found!");
781
      } else if( num_dirs < 2 ) {
782
        out("%d session found!", num_dirs);
783
      } else {
784
        out("%d sessions found!", num_dirs);
785
      }
786
    }
787
    MUTEX_SDCARD_GIVE;
788
      }
789
    } else if( strcmp(parameter, "restore") == 0 ) {
790
      if( seq_ui_backup_req || seq_ui_format_req ) {
791
    out("Ongoing session creation - please wait!");
792
      } else if( strlen(brkt) ) {
793
    out("ERROR: use 'open' if you want to load a specific session!");
794
      } else {
795
    MUTEX_SDCARD_TAKE;
796
    if( SEQ_FILE_LoadAllFiles(1) < 0 ) {
797
      out("Failed to restore session from SD Card: /SESSIONS/%s\n", seq_file_session_name);
798
    } else {
799
      out("Restored complete session from SD Card: /SESSIONS/%s\n", seq_file_session_name);
800
    }
801
    MUTEX_SDCARD_GIVE;
802
      }
803
#ifndef MBSEQV4L
804
    } else if( strcmp(parameter, "screen_saver") == 0 ) {
805
      SEQ_LCD_LOGO_ScreenSaver_Enable();
806
      if( seq_lcd_logo_screensaver_delay ) {
807
    out("Screen Saver activated.");
808
      } else {
809
    out("Screen Saver has been disabled in UTIL->OPT - please set delay to >= 1 minute!");
810
      }
811
#endif
812
    } else if( strcmp(parameter, "reset") == 0 ) {
813
      MIOS32_SYS_Reset();
814
    } else {
815
      out("Unknown command - type 'help' to list available commands!");
816
    }
817
  }
818
 
819
  return 0; // no error
820
}
821
 
822
 
823
s32 SEQ_TERMINAL_PrintHelp(void *_output_function)
824
{
825
  void (*out)(char *format, ...) = _output_function;
826
 
827
  out("Welcome to " MIOS32_LCD_BOOT_MSG_LINE1 "!");
828
  out("Following commands are available:");
829
  out("  system:         print system info");
830
  out("  memory:         print memory allocation info");
831
  out("  sdcard:         print SD Card info");
832
  out("  sdcard_format:  formats the SD Card (you will be asked for confirmation)");
833
  out("  global:         print global configuration");
834
  out("  config:         print local session configuration");
835
  out("  tracks:         print overview of all tracks");
836
  out("  track <track>:  print info about a specific track");
837
  out("  mixer:          print current mixer map");
838
  out("  song:           print current song info");
839
  out("  grooves:        print groove templates");
840
  out("  bookmarks:      print bookmarks");
841
  out("  router:         print MIDI router info");
842
  out("  tpd <string>:   print a scrolled text on the TPD");
843
  out("  set router <node> <in-port> <off|channel|all> <out-port> <off|channel|all>: change router setting");
844
  out("  set mclk_in  <in-port>  <on|off>: change MIDI IN Clock setting");
845
  out("  set mclk_out <out-port> <on|off>: change MIDI OUT Clock setting");
846
  out("  set din_testmode <on|off>: change DIN (button/encoder) testmode (current: %s)", app_din_testmode ? "on" : "off");
847
  out("  set blm_port <off|in-port>: change BLM input port (same port is used for output)");
848
  out("  set rec_quantisation <1..100>: change record quantisation (default: 10%%, current: %d%%)\n", seq_record_quantize);
849
 
850
  MUTEX_MIDIOUT_TAKE;
851
#if !defined(MIOS32_FAMILY_EMULATION)
852
  AOUT_TerminalHelp(_output_function);
853
#endif
854
#ifdef MIOS32_LCD_universal
855
  APP_LCD_TerminalHelp(_output_function);
856
#endif
857
#if !defined(MIOS32_FAMILY_EMULATION)
858
  UIP_TERMINAL_Help(_output_function);
859
#endif
860
  MUTEX_MIDIOUT_GIVE;
861
 
862
  out("  play or start:  emulates the PLAY button");
863
  out("  stop:           emulates the STOP button");
864
  out("  store or save:  stores session under the current name on SD Card");
865
  out("  restore:        restores complete session from SD Card");
866
  out("  saveas <name>:  saves the current session under a new name");
867
  out("  new <name>:     creates a new session");
868
  out("  delete <name>:  deletes a session");
869
  out("  session:        prints the current session name");
870
  out("  sessions:       prints all available sessions");
871
#ifndef MBSEQV4L
872
  out("  screen_saver:   enables the screen saver immediately");
873
#endif
874
  out("  reset:          resets the MIDIbox SEQ (!)");
875
  out("  help:           this page");
876
 
877
  return 0; // no error
878
}
879
 
880
// Help function
881
static void stringNote(char *label, u8 note)
882
{
883
  const char noteTab[12][3] = { "C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-" };
884
 
885
  // print "---" if note number is 0
886
  if( note == 0 )
887
    sprintf(label, "---  ");
888
  else {
889
    u8 octave = note / 12;
890
    note %= 12;
891
 
892
    // print semitone and octave (-2): up to 4 chars
893
    sprintf(label, "%s%d  ",
894
        noteTab[note],
895
        (int)octave-2);
896
  }
897
}
898
 
899
 
900
 
901
s32 SEQ_TERMINAL_PrintSystem(void *_output_function)
902
{
903
  void (*out)(char *format, ...) = _output_function;
904
  char str_buffer[128];
905
 
906
  out("System Informations:");
907
  out("====================");
908
  out(MIOS32_LCD_BOOT_MSG_LINE1 " " MIOS32_LCD_BOOT_MSG_LINE2 "");
909
 
910
  mios32_sys_time_t t = MIOS32_SYS_TimeGet();
911
  int hours = (t.seconds / 3600) % 24;
912
  int minutes = (t.seconds % 3600) / 60;
913
  int seconds = (t.seconds % 3600) % 60;
914
 
915
  out("Operating System: MIOS32");
916
  out("Board: " MIOS32_BOARD_STR "");
917
  out("Chip Family: " MIOS32_FAMILY_STR "");
918
  if( MIOS32_SYS_SerialNumberGet((char *)str_buffer) >= 0 )
919
    out("Serial Number: %s\n", str_buffer);
920
  else
921
    out("Serial Number: ?");
922
  out("Flash Memory Size: %d bytes\n", MIOS32_SYS_FlashSizeGet());
923
  out("RAM Size: %d bytes\n", MIOS32_SYS_RAMSizeGet());
924
 
925
  {
926
    out("MIDI IN Ports:");
927
    int num = SEQ_MIDI_PORT_InNumGet();
928
    int i;
929
    for(i=0; i<num; ++i) {
930
      mios32_midi_port_t port = SEQ_MIDI_PORT_InPortGet(i);
931
      out("  - %s (%s)\n", SEQ_MIDI_PORT_InNameGet(i), SEQ_MIDI_PORT_InCheckAvailable(port) ? "available" : "not available");
932
    }    
933
  }
934
 
935
  {
936
    out("MIDI OUT Ports:");
937
    int num = SEQ_MIDI_PORT_OutNumGet();
938
    int i;
939
    for(i=0; i<num; ++i) {
940
      mios32_midi_port_t port = SEQ_MIDI_PORT_OutPortGet(i);
941
      out("  - %s (%s)\n", SEQ_MIDI_PORT_OutNameGet(i), SEQ_MIDI_PORT_OutCheckAvailable(port) ? "available" : "not available");
942
    }    
943
  }
944
 
945
  out("Systime: %02d:%02d:%02d\n", hours, minutes, seconds);
946
  out("CPU Load: %02d%%\n", SEQ_STATISTICS_CurrentCPULoad());
947
  out("MIDI Scheduler: Alloc %3d/%3d Drops: %3d",
948
        seq_midi_out_allocated, seq_midi_out_max_allocated, seq_midi_out_dropouts);
949
 
950
  u32 stopwatch_value_max = SEQ_STATISTICS_StopwatchGetValueMax();
951
  u32 stopwatch_value = SEQ_STATISTICS_StopwatchGetValue();
952
  if( stopwatch_value_max == 0xffffffff ) {
953
    out("Stopwatch: Overrun!");
954
  } else if( !stopwatch_value_max ) {
955
    out("Stopwatch: no result yet");
956
  } else {
957
    out("Stopwatch: %d/%d uS\n", stopwatch_value, stopwatch_value_max);
958
  }
959
 
960
  u8 scale, root_selection, root;
961
  SEQ_CORE_FTS_GetScaleAndRoot(&scale, &root_selection, &root);
962
  char root_note_str[20];
963
  stringNote(root_note_str, root + 0x3c);
964
  out("Current Root Note (via %s): %s\n",
965
      root_selection == 0 ? "Keyboard" : "Selection",
966
      root_note_str);
967
 
968
#if !defined(MIOS32_FAMILY_EMULATION) && (configGENERATE_RUN_TIME_STATS || configUSE_TRACE_FACILITY)
969
  // send Run Time Stats to MIOS terminal
970
  out("FreeRTOS Task RunTime Stats:");
971
  FREERTOS_UTILS_RunTimeStats();
972
#endif
973
 
974
  out("done.");
975
 
976
  return 0; // no error
977
}
978
 
979
 
980
s32 SEQ_TERMINAL_PrintGlobalConfig(void *_output_function)
981
{
982
  void (*out)(char *format, ...) = _output_function;
983
 
984
  out("Global Configuration:");
985
  out("=====================");
986
  SEQ_FILE_GC_Debug();
987
 
988
  out("done.");
989
 
990
  return 0; // no error
991
}
992
 
993
s32 SEQ_TERMINAL_PrintBookmarks(void *_output_function)
994
{
995
  void (*out)(char *format, ...) = _output_function;
996
 
997
  out("Global Bookmarks:");
998
  out("=================");
999
  SEQ_FILE_BM_Debug(1);
1000
 
1001
  out("");
1002
 
1003
  out("Session Bookmarks:");
1004
  out("==================");
1005
  SEQ_FILE_BM_Debug(0);
1006
 
1007
  out("done.");
1008
 
1009
  return 0; // no error
1010
}
1011
 
1012
s32 SEQ_TERMINAL_PrintSessionConfig(void *_output_function)
1013
{
1014
  void (*out)(char *format, ...) = _output_function;
1015
 
1016
  out("Session Configuration:");
1017
  out("======================");
1018
  SEQ_FILE_C_Debug();
1019
 
1020
  out("done.");
1021
 
1022
  return 0; // no error
1023
}
1024
 
1025
s32 SEQ_TERMINAL_PrintTracks(void *_output_function)
1026
{
1027
  void (*out)(char *format, ...) = _output_function;
1028
  char str_buffer[128];
1029
 
1030
  out("Track Overview:");
1031
  out("===============");
1032
 
1033
  out("| Track | Mode  | Layer P/T/I | Steps P/T | Length | Port  | Chn. | Muted |");
1034
  out("+-------+-------+-------------+-----------+--------+-------+------+-------+");
1035
 
1036
  u8 track;
1037
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) {
1038
    seq_event_mode_t event_mode = SEQ_CC_Get(track, SEQ_CC_MIDI_EVENT_MODE);
1039
    u16 num_instruments = SEQ_TRG_NumInstrumentsGet(track);
1040
    u16 num_par_layers = SEQ_PAR_NumLayersGet(track);
1041
    u16 num_par_steps = SEQ_PAR_NumStepsGet(track);
1042
    u16 num_trg_layers = SEQ_TRG_NumLayersGet(track);
1043
    u16 num_trg_steps = SEQ_TRG_NumStepsGet(track);
1044
    u16 length = (u16)SEQ_CC_Get(track, SEQ_CC_LENGTH) + 1;
1045
    mios32_midi_port_t midi_port = SEQ_CC_Get(track, SEQ_CC_MIDI_PORT);
1046
    u8 midi_chn = SEQ_CC_Get(track, SEQ_CC_MIDI_CHANNEL) + 1;
1047
 
1048
    sprintf(str_buffer, "| G%dT%d  | %s |",
1049
        (track/4)+1, (track%4)+1,
1050
        SEQ_LAYER_GetEvntModeName(event_mode));
1051
 
1052
    sprintf((char *)(str_buffer + strlen(str_buffer)), "   %2d/%2d/%2d  |  %3d/%3d  |   %3d  | %s%c |  %2d  |",
1053
        num_par_layers, num_trg_layers, num_instruments,
1054
        num_par_steps, num_trg_steps,
1055
        length,
1056
        SEQ_MIDI_PORT_OutNameGet(SEQ_MIDI_PORT_OutIxGet(midi_port)),
1057
        SEQ_MIDI_PORT_OutCheckAvailable(midi_port) ? ' ' : '*',
1058
        midi_chn);
1059
 
1060
    if( seq_core_trk_muted & (1 << track) )
1061
      sprintf((char *)(str_buffer + strlen(str_buffer)), "  yes  |");
1062
    else if( seq_core_trk[track].layer_muted )
1063
      sprintf((char *)(str_buffer + strlen(str_buffer)), " layer |");
1064
    else
1065
      sprintf((char *)(str_buffer + strlen(str_buffer)), "  no   |");
1066
 
1067
    out(str_buffer);
1068
  }
1069
 
1070
  out("+-------+-------+-------------+-----------+--------+-------+------+-------+");
1071
 
1072
  out("done.");
1073
 
1074
  return 0; // no error
1075
}
1076
 
1077
s32 SEQ_TERMINAL_PrintTrack(void *_output_function, u8 track)
1078
{
1079
  void (*out)(char *format, ...) = _output_function;
1080
 
1081
  out("Track Parameters of G%dT%d", (track/4)+1, (track%4)+1);
1082
  out("========================");
1083
 
1084
  SEQ_FILE_T_Debug(track);
1085
 
1086
  out("done.");
1087
 
1088
  return 0; // no error
1089
}
1090
 
1091
s32 SEQ_TERMINAL_PrintCurrentMixerMap(void *_output_function)
1092
{
1093
  void (*out)(char *format, ...) = _output_function;
1094
 
1095
  char str_buffer[128];
1096
  u8 map = SEQ_MIXER_NumGet();
1097
  int i;
1098
 
1099
  out("Mixer Map #%3d\n", map+1);
1100
  out("==============");
1101
 
1102
  out("|Num|Port|Chn|Prg|Vol|Pan|Rev|Cho|Mod|CC1|CC2|CC3|CC4|C1A|C2A|C3A|C4A|");
1103
  out("+---+----+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+");
1104
 
1105
  for(i=0; i<16; ++i) {
1106
    sprintf(str_buffer, "|%3d|%s|", i, SEQ_MIDI_PORT_OutNameGet(SEQ_MIDI_PORT_OutIxGet(SEQ_MIXER_Get(i, SEQ_MIXER_PAR_PORT))));
1107
 
1108
    int par;
1109
 
1110
    for(par=1; par<2; ++par)
1111
      sprintf((char *)(str_buffer + strlen(str_buffer)), "%3d|", SEQ_MIXER_Get(i, par)+1);
1112
 
1113
    for(par=2; par<12; ++par) {
1114
      u8 value = SEQ_MIXER_Get(i, par);
1115
      if( value )
1116
    sprintf((char *)(str_buffer + strlen(str_buffer)), "%3d|", value-1);
1117
      else
1118
    sprintf((char *)(str_buffer + strlen(str_buffer)), " - |");
1119
    }
1120
 
1121
    for(par=12; par<16; ++par)
1122
      sprintf((char *)(str_buffer + strlen(str_buffer)), "%3d|", SEQ_MIXER_Get(i, par));
1123
 
1124
    out("%s\n", str_buffer);
1125
  }
1126
 
1127
  out("+---+----+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+");
1128
  out("done.");
1129
 
1130
  return 0; // no error
1131
}
1132
 
1133
 
1134
s32 SEQ_TERMINAL_PrintCurrentSong(void *_output_function)
1135
{
1136
  void (*out)(char *format, ...) = _output_function;
1137
 
1138
  u8 song = SEQ_SONG_NumGet();
1139
 
1140
  out("Song #%2d\n", song+1);
1141
  out("========");
1142
 
1143
  out("Name: '%s'\n", seq_song_name);
1144
  MIOS32_MIDI_SendDebugHexDump((u8 *)&seq_song_steps[0], SEQ_SONG_NUM_STEPS*sizeof(seq_song_step_t));
1145
 
1146
  out("done.");
1147
 
1148
  return 0; // no error
1149
}
1150
 
1151
s32 SEQ_TERMINAL_PrintGrooveTemplates(void *_output_function)
1152
{
1153
  void (*out)(char *format, ...) = _output_function;
1154
 
1155
  out("Groove Templates:");
1156
  out("=================");
1157
  SEQ_FILE_G_Debug();
1158
 
1159
  out("done.");
1160
 
1161
  return 0; // no error
1162
}
1163
 
1164
s32 SEQ_TERMINAL_PrintMemoryInfo(void *_output_function)
1165
{
2434 tk 1166
#if defined(MIOS32_FAMILY_EMULATION)
1167
  void (*out)(char *format, ...) = _output_function;
1168
  out("Not supported in emulation!");
1169
#else
1170
  MUTEX_MIDIOUT_TAKE;
1171
  vPortMallocDebugInfo();
1172
  MUTEX_MIDIOUT_GIVE;
2414 pcbatterij 1173
#endif
1174
 
1175
  return 0; // no error
1176
}
1177
 
1178
 
1179
///////////////////////////////////////////////////////////////////
1180
// These time and date functions and other bits of following code were adapted from 
1181
// Rickey's world of Microelectronics under the creative commons 2.5 license.
1182
// http://www.8051projects.net/mmc-sd-interface-fat16/final-code.php
1183
static void ShowFatTime(u32 ThisTime, char* msg)
1184
{
1185
   u8 AM = 1;
1186
 
1187
   int Hour, Minute, Second;
1188
 
1189
   Hour = ThisTime >> 11;        // bits 15 through 11 hold Hour...
1190
   Minute = ThisTime & 0x07E0;   // bits 10 through 5 hold Minute... 0000 0111 1110 0000
1191
   Minute = Minute >> 5;
1192
   Second = ThisTime & 0x001F;   //bits 4 through 0 hold Second...   0000 0000 0001 1111
1193
 
1194
   if( Hour > 11 )
1195
   {
1196
      AM = 0;
1197
      if( Hour > 12 )
1198
         Hour -= 12;
1199
   }
1200
 
1201
   sprintf( msg, "%02d:%02d:%02d %s", Hour, Minute, Second*2,
1202
         (AM)?"AM":"PM");
1203
   return;
1204
}
1205
 
1206
static void ShowFatDate(u32 ThisDate, char* msg)
1207
{
1208
 
1209
   int Year, Month, Day;
1210
 
1211
   Year = ThisDate >> 9;         // bits 15 through 9 hold year...
1212
   Month = ThisDate & 0x01E0;    // bits 8 through 5 hold month... 0000 0001 1110 0000
1213
   Month = Month >> 5;
1214
   Day = ThisDate & 0x001F;      //bits 4 through 0 hold day...    0000 0000 0001 1111
1215
   sprintf( msg, "%02d/%02d/%02d", Month, Day, Year-20);
1216
   return;
1217
}
1218
 
1219
 
1220
s32 SEQ_TERMINAL_PrintSdCardInfo(void *_output_function)
1221
{
1222
  void (*out)(char *format, ...) = _output_function;
1223
 
1224
  FRESULT res;
1225
  FILINFO fno;
1226
  DIR dir;
1227
  char *fn;
1228
  char str_buffer[128];
1229
 
1230
  out("SD Card Informations");
1231
  out("====================");
1232
 
1233
#if !defined(MIOS32_FAMILY_EMULATION)
1234
  // this yield ensures, that Debug Messages are sent before we continue the execution
1235
  // Since MIOS Studio displays the time at which the messages arrived, this allows
1236
  // us to measure the delay of following operations
1237
  taskYIELD();
1238
 
1239
  MUTEX_SDCARD_TAKE;
1240
  FILE_PrintSDCardInfos();
1241
  MUTEX_SDCARD_GIVE;
1242
#endif
1243
 
1244
  out("");
1245
  out("Reading Root Directory");
1246
  out("======================");
1247
 
1248
  taskYIELD();
1249
 
1250
  if( !FILE_SDCardAvailable() ) {
1251
    sprintf(str_buffer, "not connected");
1252
  } else if( !FILE_VolumeAvailable() ) {
1253
    sprintf(str_buffer, "Invalid FAT");
1254
  } else {
1255
    out("Retrieving SD Card informations - please wait!");
1256
    MUTEX_MIDIOUT_GIVE;
1257
    MUTEX_SDCARD_TAKE;
1258
    FILE_UpdateFreeBytes();
1259
    MUTEX_SDCARD_GIVE;
1260
    MUTEX_MIDIOUT_TAKE;
1261
 
1262
    sprintf(str_buffer, "'%s': %u of %u MB free",
1263
        FILE_VolumeLabel(),
1264
        (unsigned int)(FILE_VolumeBytesFree()/1000000),
1265
        (unsigned int)(FILE_VolumeBytesTotal()/1000000));
1266
  }
1267
  out("SD Card: %s\n", str_buffer);
1268
 
1269
  taskYIELD();
1270
 
1271
#if _USE_LFN
1272
  static char lfn[_MAX_LFN * (_DF1S ? 2 : 1) + 1];
1273
  fno.lfname = lfn;
1274
  fno.lfsize = sizeof(lfn);
1275
#endif
1276
 
1277
  MUTEX_SDCARD_TAKE;
1278
  if( (res=f_opendir(&dir, "/")) != FR_OK ) {
1279
    out("Failed to open root directory - error status: %d\n", res);
1280
  } else {
1281
    while( (f_readdir(&dir, &fno) == FR_OK) && fno.fname[0] ) {
1282
#if _USE_LFN
1283
      fn = *fno.lfname ? fno.lfname : fno.fname;
1284
#else
1285
      fn = fno.fname;
1286
#endif
1287
      char date[10];
1288
      ShowFatDate(fno.fdate,(char*)&date);
1289
      char time[12];
1290
      ShowFatTime(fno.ftime,(char*)&time);
1291
      out("[%s%s%s%s%s%s%s] %s  %s   %s %u %s\n",
1292
        (fno.fattrib & AM_RDO ) ? "r" : ".",
1293
        (fno.fattrib & AM_HID ) ? "h" : ".",
1294
        (fno.fattrib & AM_SYS ) ? "s" : ".",
1295
        (fno.fattrib & AM_VOL ) ? "v" : ".",
1296
        (fno.fattrib & AM_LFN ) ? "l" : ".",
1297
        (fno.fattrib & AM_DIR ) ? "d" : ".",
1298
        (fno.fattrib & AM_ARC ) ? "a" : ".",
1299
        date,time,
1300
        (fno.fattrib & AM_DIR) ? "<DIR>" : " ",
1301
        fno.fsize,fn);
1302
    }
1303
  }
1304
  MUTEX_SDCARD_GIVE;
1305
 
1306
  taskYIELD();
1307
 
1308
  out("");
1309
  out("Checking SD Card at application layer");
1310
  out("=====================================");
1311
 
1312
  out("Current session: /SESSIONS/%s\n", seq_file_session_name);
1313
 
1314
  {
1315
    u8 bank;
1316
    for(bank=0; bank<SEQ_FILE_B_NUM_BANKS; ++bank) {
1317
      int num_patterns = SEQ_FILE_B_NumPatterns(bank);
1318
      if( num_patterns )
1319
    out("File /SESSIONS/%s/MBSEQ_B%d.V4: valid (%d patterns)\n", seq_file_session_name, bank+1, num_patterns);
1320
      else
1321
    out("File /SESSIONS/%s/MBSEQ_B%d.V4: doesn't exist\n", seq_file_session_name, bank+1, num_patterns);
1322
    }
1323
 
1324
    int num_maps = SEQ_FILE_M_NumMaps();
1325
    if( num_maps )
1326
      out("File /SESSIONS/%s/MBSEQ_M.V4: valid (%d mixer maps)\n", seq_file_session_name, num_maps);
1327
    else
1328
      out("File /SESSIONS/%s/MBSEQ_M.V4: doesn't exist\n", seq_file_session_name);
1329
 
1330
    int num_songs = SEQ_FILE_S_NumSongs();
1331
    if( num_songs )
1332
      out("File /SESSIONS/%s/MBSEQ_S.V4: valid (%d songs)\n", seq_file_session_name, num_songs);
1333
    else
1334
      out("File /SESSIONS/%s/MBSEQ_S.V4: doesn't exist\n", seq_file_session_name);
1335
 
1336
    if( SEQ_FILE_G_Valid() )
1337
      out("File /SESSIONS/%s/MBSEQ_G.V4: valid\n", seq_file_session_name);
1338
    else
1339
      out("File /SESSIONS/%s/MBSEQ_G.V4: doesn't exist\n", seq_file_session_name);
1340
 
1341
    if( SEQ_FILE_BM_Valid(0) )
1342
      out("File /SESSIONS/%s/MBSEQ_BM.V4: valid\n", seq_file_session_name);
1343
    else
1344
      out("File /SESSIONS/%s/MBSEQ_BM.V4: doesn't exist\n", seq_file_session_name);
1345
 
1346
    if( SEQ_FILE_C_Valid() )
1347
      out("File /SESSIONS/%s/MBSEQ_C.V4: valid\n", seq_file_session_name);
1348
    else
1349
      out("File /SESSIONS/%s/MBSEQ_C.V4: doesn't exist\n", seq_file_session_name);
1350
 
1351
    if( SEQ_FILE_GC_Valid() )
1352
      out("File /MBSEQ_C.V4: valid");
1353
    else
1354
      out("File /MBSEQ_C.V4: doesn't exist");
1355
 
1356
    if( SEQ_FILE_BM_Valid(1) )
1357
      out("File /MBSEQ_BM.V4: valid");
1358
    else
1359
      out("File /MBSEQ_BM.V4: doesn't exist");
1360
 
1361
#ifndef MBSEQV4L    
1362
    if( SEQ_FILE_HW_Valid() )
1363
      out("File /MBSEQ_HW.V4: valid");
1364
    else
1365
      out("File /MBSEQ_HW.V4: doesn't exist or hasn't been re-loaded");
1366
#else
1367
    if( SEQ_FILE_HW_Valid() )
1368
      out("File /MBSEQ_HW.V4L: valid");
1369
    else
1370
      out("File /MBSEQ_HW.V4L: doesn't exist or hasn't been re-loaded");
1371
#endif
1372
  }
1373
 
1374
  out("done.");
1375
 
1376
  return 0; // no error
1377
}
1378
 
1379
 
1380
s32 SEQ_TERMINAL_PrintRouterInfo(void *_output_function)
1381
{
1382
  void (*out)(char *format, ...) = _output_function;
1383
 
1384
  out("MIDI Router Nodes (change with 'set router <node> <in-port> <channel> <out-port> <channel>)");
1385
  out("Example: set router 1 IN1 all USB1 all");
1386
 
1387
  u8 node;
1388
  seq_midi_router_node_t *n = &seq_midi_router_node[0];
1389
  for(node=0; node<SEQ_MIDI_ROUTER_NUM_NODES; ++node, ++n) {
1390
 
1391
    char src_chn[10];
1392
    if( !n->src_chn )
1393
      sprintf(src_chn, "off");
1394
    else if( n->src_chn > 16 )
1395
      sprintf(src_chn, "all");
1396
    else
1397
      sprintf(src_chn, "#%2d", n->src_chn);
1398
 
1399
    char dst_chn[10];
1400
    if( !n->dst_chn )
1401
      sprintf(dst_chn, "off");
1402
    else if( n->dst_chn == 17 )
1403
      sprintf(dst_chn, "All");
1404
    else if( n->dst_chn == 18 )
1405
      sprintf(dst_chn, "Trk");
1406
    else if( n->dst_chn >= 19 )
1407
      sprintf(dst_chn, "STk");
1408
    else
1409
      sprintf(dst_chn, "#%2d", n->dst_chn);
1410
 
1411
    out("  %2d  SRC:%s %s  DST:%s %s",
1412
    node+1,
1413
    SEQ_MIDI_PORT_InNameGet(SEQ_MIDI_PORT_InIxGet(n->src_port)),
1414
    src_chn,
1415
    SEQ_MIDI_PORT_OutNameGet(SEQ_MIDI_PORT_OutIxGet(n->dst_port)),
1416
    dst_chn);
1417
  }
1418
 
1419
  out("");
1420
  out("MIDI Clock (change with 'set mclk_in <in-port> <on|off>' resp. 'set mclk_out <out-port> <on|off>')");
1421
 
1422
  int num_mclk_ports = SEQ_MIDI_PORT_ClkNumGet();
1423
  int port_ix;
1424
  for(port_ix=0; port_ix<num_mclk_ports; ++port_ix) {
1425
    mios32_midi_port_t mclk_port = SEQ_MIDI_PORT_ClkPortGet(port_ix);
1426
 
1427
    s32 enab_rx = SEQ_MIDI_ROUTER_MIDIClockInGet(mclk_port);
1428
    if( !SEQ_MIDI_PORT_ClkCheckAvailable(mclk_port) )
1429
      enab_rx = -1; // MIDI In port not available
1430
 
1431
    s32 enab_tx = SEQ_MIDI_ROUTER_MIDIClockOutGet(mclk_port);
1432
    if( !SEQ_MIDI_PORT_ClkCheckAvailable(mclk_port) )
1433
      enab_tx = -1; // MIDI In port not available
1434
 
1435
    out("  %s  IN:%s  OUT:%s\n",
1436
    SEQ_MIDI_PORT_ClkNameGet(port_ix),
1437
    (enab_rx == 0) ? "off" : ((enab_rx == 1) ? "on " : "---"),
1438
    (enab_tx == 0) ? "off" : ((enab_tx == 1) ? "on " : "---"));
1439
  }
1440
 
1441
  return 0; // no error
1442
}