Subversion Repositories svn.mios32

Rev

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

Rev Author Line No. Line
1260 tk 1
// $Id: terminal.c 2425 2016-11-03 00:44:22Z tk $
2
/*
3
 * The command/configuration 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>
1653 tk 20
#include <ff.h>
1260 tk 21
 
1492 tk 22
#include <midi_port.h>
23
#include <midi_router.h>
24
#include <midimon.h>
1633 tk 25
#include <app_lcd.h>
1543 tk 26
#include <file.h>
1492 tk 27
 
1260 tk 28
#include "app.h"
1653 tk 29
#include "terminal.h"
1260 tk 30
#include "midio_patch.h"
1387 tk 31
#include "uip_terminal.h"
1260 tk 32
#include "tasks.h"
33
#include "midio_file.h"
34
#include "midio_file_p.h"
1543 tk 35
#include "mid_file.h"
1260 tk 36
 
1543 tk 37
 
1260 tk 38
/////////////////////////////////////////////////////////////////////////////
39
// Local defines
40
/////////////////////////////////////////////////////////////////////////////
41
 
1543 tk 42
#define STRING_MAX 100 // recommended size for file transfers via FILE_BrowserHandler()
1260 tk 43
 
44
 
45
/////////////////////////////////////////////////////////////////////////////
46
// Local variables
47
/////////////////////////////////////////////////////////////////////////////
48
 
49
static char line_buffer[STRING_MAX];
50
static u16 line_ix;
51
 
52
 
53
/////////////////////////////////////////////////////////////////////////////
54
// Local prototypes
55
/////////////////////////////////////////////////////////////////////////////
56
 
1543 tk 57
static s32 TERMINAL_ParseFilebrowser(mios32_midi_port_t port, char byte);
1260 tk 58
 
59
 
60
/////////////////////////////////////////////////////////////////////////////
61
// Initialisation
62
/////////////////////////////////////////////////////////////////////////////
63
s32 TERMINAL_Init(u32 mode)
64
{
1543 tk 65
  // install the callback function which is called on incoming characters from MIOS Terminal
1260 tk 66
  MIOS32_MIDI_DebugCommandCallback_Init(TERMINAL_Parse);
67
 
1543 tk 68
  // install the callback function which is called on incoming characters from MIOS Filebrowser
69
  MIOS32_MIDI_FilebrowserCommandCallback_Init(TERMINAL_ParseFilebrowser);
70
 
1260 tk 71
  // clear line buffer
72
  line_buffer[0] = 0;
73
  line_ix = 0;
74
 
75
  return 0; // no error
76
}
77
 
78
 
79
/////////////////////////////////////////////////////////////////////////////
80
// help function which parses a decimal or hex value
81
// returns >= 0 if value is valid
82
// returns -1 if value is invalid
83
/////////////////////////////////////////////////////////////////////////////
84
static s32 get_dec(char *word)
85
{
86
  if( word == NULL )
87
    return -1;
88
 
89
  char *next;
90
  long l = strtol(word, &next, 0);
91
 
92
  if( word == next )
93
    return -1;
94
 
95
  return l; // value is valid
96
}
97
 
98
 
99
/////////////////////////////////////////////////////////////////////////////
100
// help function which parses for on or off
101
// returns 0 if 'off', 1 if 'on', -1 if invalid
102
/////////////////////////////////////////////////////////////////////////////
1653 tk 103
//static s32 get_on_off(char *word)
104
//{
105
//  if( strcmp(word, "on") == 0 )
106
//    return 1;
107
//
108
//  if( strcmp(word, "off") == 0 )
109
//    return 0;
110
//
111
//  return -1;
112
//}
1260 tk 113
 
114
 
115
/////////////////////////////////////////////////////////////////////////////
116
// Parser
117
/////////////////////////////////////////////////////////////////////////////
1333 tk 118
s32 TERMINAL_Parse(mios32_midi_port_t port, char byte)
1260 tk 119
{
120
  // temporary change debug port (will be restored at the end of this function)
121
  mios32_midi_port_t prev_debug_port = MIOS32_MIDI_DebugPortGet();
122
  MIOS32_MIDI_DebugPortSet(port);
123
 
124
  if( byte == '\r' ) {
125
    // ignore
126
  } else if( byte == '\n' ) {
127
    MUTEX_MIDIOUT_TAKE;
128
    TERMINAL_ParseLine(line_buffer, MIOS32_MIDI_SendDebugMessage);
129
    MUTEX_MIDIOUT_GIVE;
130
    line_ix = 0;
131
    line_buffer[line_ix] = 0;
132
  } else if( line_ix < (STRING_MAX-1) ) {
133
    line_buffer[line_ix++] = byte;
134
    line_buffer[line_ix] = 0;
135
  }
136
 
137
  // restore debug port
138
  MIOS32_MIDI_DebugPortSet(prev_debug_port);
139
 
140
  return 0; // no error
141
}
142
 
143
 
144
/////////////////////////////////////////////////////////////////////////////
1543 tk 145
// Parser for Filebrowser
146
/////////////////////////////////////////////////////////////////////////////
147
s32 TERMINAL_ParseFilebrowser(mios32_midi_port_t port, char byte)
148
{
149
  if( byte == '\r' ) {
150
    // ignore
151
  } else if( byte == '\n' ) {
152
 
153
    // extra for MIDIO128: ensure that recording not active to avoid conflict with write operations!
154
    if( MID_FILE_RecordingEnabled() ) {
155
      MID_FILE_SetRecordMode(0);
156
    }
157
 
158
    MUTEX_MIDIOUT_TAKE;
159
    MUTEX_SDCARD_TAKE;
160
    FILE_BrowserHandler(port, line_buffer);
161
    MUTEX_SDCARD_GIVE;
162
    MUTEX_MIDIOUT_GIVE;
163
    line_ix = 0;
164
    line_buffer[line_ix] = 0;
165
  } else if( line_ix < (STRING_MAX-1) ) {
166
    line_buffer[line_ix++] = byte;
167
    line_buffer[line_ix] = 0;
168
  }
169
 
170
  return 0; // no error
171
}
172
 
173
 
174
/////////////////////////////////////////////////////////////////////////////
1260 tk 175
// Parser for a complete line - also used by shell.c for telnet
176
/////////////////////////////////////////////////////////////////////////////
177
s32 TERMINAL_ParseLine(char *input, void *_output_function)
178
{
179
  void (*out)(char *format, ...) = _output_function;
180
  char *separators = " \t";
181
  char *brkt;
182
  char *parameter;
183
 
1387 tk 184
  if( UIP_TERMINAL_ParseLine(input, _output_function) > 0 )
185
    return 0; // command parsed by UIP Terminal
186
 
1492 tk 187
  if( MIDIMON_TerminalParseLine(input, _output_function) > 0 )
188
    return 0; // command parsed
189
 
190
  if( MIDI_ROUTER_TerminalParseLine(input, _output_function) > 0 )
191
    return 0; // command parsed
192
 
1633 tk 193
#ifdef MIOS32_LCD_universal
194
  if( APP_LCD_TerminalParseLine(input, _output_function) >= 1 )
195
    return 0; // command parsed
196
#endif
197
 
1260 tk 198
  if( (parameter = strtok_r(input, separators, &brkt)) ) {
199
    if( strcmp(parameter, "help") == 0 ) {
200
      out("Welcome to " MIOS32_LCD_BOOT_MSG_LINE1 "!");
201
      out("Following commands are available:");
202
      out("  system:                           print system info");
1653 tk 203
      out("  memory:                           print memory allocation info\n");
204
      out("  sdcard:                           print SD Card info\n");
205
      out("  sdcard_format:                    formats the SD Card (you will be asked for confirmation)\n");
1387 tk 206
      UIP_TERMINAL_Help(_output_function);
1492 tk 207
      MIDIMON_TerminalHelp(_output_function);
208
      MIDI_ROUTER_TerminalHelp(_output_function);
1633 tk 209
#ifdef MIOS32_LCD_universal
210
      APP_LCD_TerminalHelp(_output_function);
211
#endif
1292 tk 212
      out("  set dout <pin> <0|1>:             directly sets DOUT (all or 0..%d) to given level (1 or 0)", MIOS32_SRIO_NUM_SR*8 - 1);
1264 tk 213
      out("  save <name>:                      stores current config on SD Card");
214
      out("  load <name>:                      restores config from SD Card");
1604 tk 215
      out("  show file:                        shows the current configuration file");
1320 tk 216
      out("  msd <on|off>:                     enables Mass Storage Device driver");
1260 tk 217
      out("  reset:                            resets the MIDIbox (!)\n");
218
      out("  help:                             this page");
219
      out("  exit:                             (telnet only) exits the terminal");
220
    } else if( strcmp(parameter, "system") == 0 ) {
221
      TERMINAL_PrintSystem(_output_function);
1653 tk 222
    } else if( strcmp(parameter, "memory") == 0 ) {
223
      TERMINAL_PrintMemoryInfo(out);
224
    } else if( strcmp(parameter, "sdcard") == 0 ) {
225
      TERMINAL_PrintSdCardInfo(out);
226
    } else if( strcmp(parameter, "sdcard_format") == 0 ) {
227
      if( !brkt || strcasecmp(brkt, "yes, I'm sure") != 0 ) {
228
    out("ATTENTION: this command will format your SD Card!!!");
229
    out("           ALL DATA WILL BE DELETED FOREVER!!!");
230
    out("           Check the current content with the 'sdcard' command");
231
    out("           Create a backup on your computer if necessary!");
232
    out("To start formatting, please enter: sdcard_format yes, I'm sure");
233
    if( brkt ) {
234
      out("('%s' wasn't the right \"password\")", brkt);
235
    }
236
      } else {
237
    MUTEX_SDCARD_TAKE;
238
    out("Formatting SD Card...");
239
    FRESULT res;
240
    if( (res=f_mkfs(0,0,0)) != FR_OK ) {
241
      out("Formatting failed with error code: %d!", res);
242
    } else {
243
      out("...with success!");
244
      MIDIO_FILE_UnloadAllFiles();
245
      MIDIO_FILE_CreateDefaultFiles();
246
    }
247
    MUTEX_SDCARD_GIVE;
248
      }
1320 tk 249
    } else if( strcmp(parameter, "msd") == 0 ) {
250
      char *arg = NULL;
251
      if( (arg = strtok_r(NULL, separators, &brkt)) ) {
252
    if( strcmp(arg, "on") == 0 ) {
253
      if( TASK_MSD_EnableGet() ) {
254
        out("Mass Storage Device Mode already activated!\n");
255
      } else {
256
        out("Mass Storage Device Mode activated - USB MIDI will be disabled!!!\n");
257
        // wait a second to ensure that this message is print in MIOS Terminal
258
        int d;
259
        for(d=0; d<1000; ++d)
260
          MIOS32_DELAY_Wait_uS(1000);
261
        // activate MSD mode
262
        TASK_MSD_EnableSet(1);
263
      }
264
    } else if( strcmp(arg, "off") == 0 ) {
265
      if( !TASK_MSD_EnableGet() ) {
266
        out("Mass Storage Device Mode already deactivated!\n");
267
      } else {
268
        out("Mass Storage Device Mode deactivated - USB MIDI will be available again.n");
269
        TASK_MSD_EnableSet(0);
270
      }
271
    } else
272
      arg = NULL;
273
      }
274
      if( arg == NULL ) {
275
    out("Please enter 'msd on' or 'msd off'\n");
276
      }      
1264 tk 277
    } else if( strcmp(parameter, "save") == 0 ) {
278
      if( !(parameter = strtok_r(NULL, separators, &brkt)) ) {
279
    out("ERROR: please specify filename for patch (up to 8 characters)!");
1260 tk 280
      } else {
1264 tk 281
    if( strlen(parameter) > 8 ) {
282
      out("ERROR: 8 characters maximum!");
283
    } else {
284
      s32 status = MIDIO_PATCH_Store(parameter);
285
      if( status >= 0 ) {
286
        out("Patch '%s' stored on SD Card!", parameter);
287
      } else {
288
        out("ERROR: failed to store patch '%s' on SD Card (status %d)!", parameter, status);
289
      }
290
    }
1260 tk 291
      }
1264 tk 292
    } else if( strcmp(parameter, "load") == 0 ) {
293
      if( !(parameter = strtok_r(NULL, separators, &brkt)) ) {
294
    out("ERROR: please specify filename for patch (up to 8 characters)!");
1260 tk 295
      } else {
1264 tk 296
    if( strlen(parameter) > 8 ) {
297
      out("ERROR: 8 characters maximum!");
298
    } else {
299
      s32 status = MIDIO_PATCH_Load(parameter);
300
      if( status >= 0 ) {
301
        out("Patch '%s' loaded from SD Card!", parameter);
302
      } else {
303
        out("ERROR: failed to load patch '%s' on SD Card (status %d)!", parameter, status);
304
      }
305
    }
1260 tk 306
      }
307
    } else if( strcmp(parameter, "show") == 0 ) {
1604 tk 308
      if( !(parameter = strtok_r(NULL, separators, &brkt)) ) {
309
    out("ERROR: please specify the item which should be displayed!");
310
      } else {
311
    if( strcmp(parameter, "file") == 0 )
312
      MIDIO_FILE_P_Debug();
313
    else {
314
      out("ERROR: invalid item which should be showed - see help for available items!");
315
    }
316
      }
1260 tk 317
    } else if( strcmp(parameter, "reset") == 0 ) {
318
      MIOS32_SYS_Reset();
319
    } else if( strcmp(parameter, "set") == 0 ) {
320
      if( (parameter = strtok_r(NULL, separators, &brkt)) ) {
1492 tk 321
    if( strcmp(parameter, "dout") == 0 ) {
1260 tk 322
      s32 pin = -1;
323
      if( (parameter = strtok_r(NULL, separators, &brkt)) ) {
324
        if( strcmp(parameter, "all") == 0 ) {
325
          pin = -42;
326
        } else {
327
          pin = get_dec(parameter);
328
        }
329
      }
330
 
331
      if( (pin < 0 && pin != -42) || pin >= (MIOS32_SRIO_NUM_SR*8) ) {
332
        out("Pin number should be between 0..%d", MIOS32_SRIO_NUM_SR*8 - 1);
333
      } else {
334
        s32 value = -1;
335
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
336
          value = get_dec(parameter);
337
 
338
        if( value < 0 || value > 1 ) {
339
          out("Expecting value 1 or 0 for DOUT pin %d", pin);
340
        } else {
341
          if( pin == -42 ) {
342
        for(pin=0; pin<(MIOS32_SRIO_NUM_SR*8); ++pin)
343
          MIOS32_DOUT_PinSet(pin, value);
344
        out("All DOUT pins set to %d", value);
345
          } else {
346
        MIOS32_DOUT_PinSet(pin, value);
347
        out("DOUT Pin %d (SR#%d.D%d) set to %d", pin, (pin/8)+1, 7-(pin%8), value);
348
          }
349
        }
350
      }
351
    } else {
352
      out("Unknown set parameter: '%s'!", parameter);
353
    }
354
      } else {
355
    out("Missing parameter after 'set'!");
356
      }
357
    } else {
358
      out("Unknown command - type 'help' to list available commands!");
359
    }
360
  }
361
 
362
  return 0; // no error
363
}
364
 
365
 
366
/////////////////////////////////////////////////////////////////////////////
367
// System Informations
368
/////////////////////////////////////////////////////////////////////////////
1653 tk 369
s32 TERMINAL_PrintSystem(void *_output_function)
1260 tk 370
{
371
  void (*out)(char *format, ...) = _output_function;
372
 
373
  out("Application: " MIOS32_LCD_BOOT_MSG_LINE1);
374
 
1492 tk 375
  MIDIMON_TerminalPrintConfig(out);
1260 tk 376
 
1653 tk 377
#if !defined(MIOS32_FAMILY_EMULATION) && configGENERATE_RUN_TIME_STATS
378
  // send Run Time Stats to MIOS terminal
379
  out("FreeRTOS Task RunTime Stats:\n");
380
  FREERTOS_UTILS_RunTimeStats();
381
#endif
382
 
1260 tk 383
  return 0; // no error
384
}
1653 tk 385
 
386
/////////////////////////////////////////////////////////////////////////////
387
// Memory allocation Informations
388
/////////////////////////////////////////////////////////////////////////////
389
s32 TERMINAL_PrintMemoryInfo(void *_output_function)
390
{
2425 tk 391
  void (*out)(char *format, ...) = _output_function;
1653 tk 392
 
2425 tk 393
  out("Not supported yet");
1653 tk 394
 
395
  return 0; // no error
396
}
397
 
398
/////////////////////////////////////////////////////////////////////////////
399
// SDCard Informations
400
/////////////////////////////////////////////////////////////////////////////
401
///////////////////////////////////////////////////////////////////
402
// These time and date functions and other bits of following code were adapted from 
403
// Rickey's world of Microelectronics under the creative commons 2.5 license.
404
// http://www.8051projects.net/mmc-sd-interface-fat16/final-code.php
405
static void ShowFatTime(u32 ThisTime, char* msg)
406
{
407
   u8 AM = 1;
408
 
409
   int Hour, Minute, Second;
410
 
411
   Hour = ThisTime >> 11;        // bits 15 through 11 hold Hour...
412
   Minute = ThisTime & 0x07E0;   // bits 10 through 5 hold Minute... 0000 0111 1110 0000
413
   Minute = Minute >> 5;
414
   Second = ThisTime & 0x001F;   //bits 4 through 0 hold Second...   0000 0000 0001 1111
415
 
416
   if( Hour > 11 )
417
   {
418
      AM = 0;
419
      if( Hour > 12 )
420
         Hour -= 12;
421
   }
422
 
423
   sprintf( msg, "%02d:%02d:%02d %s", Hour, Minute, Second*2,
424
         (AM)?"AM":"PM");
425
   return;
426
}
427
 
428
static void ShowFatDate(u32 ThisDate, char* msg)
429
{
430
 
431
   int Year, Month, Day;
432
 
433
   Year = ThisDate >> 9;         // bits 15 through 9 hold year...
434
   Month = ThisDate & 0x01E0;    // bits 8 through 5 hold month... 0000 0001 1110 0000
435
   Month = Month >> 5;
436
   Day = ThisDate & 0x001F;      //bits 4 through 0 hold day...    0000 0000 0001 1111
437
   sprintf( msg, "%02d/%02d/%02d", Month, Day, Year-20);
438
   return;
439
}
440
 
441
s32 TERMINAL_PrintSdCardInfo(void *_output_function)
442
{
443
  void (*out)(char *format, ...) = _output_function;
444
 
445
  FRESULT res;
446
  FILINFO fno;
447
  DIR dir;
448
  char *fn;
449
  char str_buffer[128];
450
 
451
  MUTEX_MIDIOUT_TAKE;
452
 
453
  out("SD Card Informations\n");
454
  out("====================\n");
455
 
456
#if !defined(MIOS32_FAMILY_EMULATION)
457
  // this yield ensures, that Debug Messages are sent before we continue the execution
458
  // Since MIOS Studio displays the time at which the messages arrived, this allows
459
  // us to measure the delay of following operations
460
  taskYIELD();
461
 
462
  MUTEX_SDCARD_TAKE;
463
  FILE_PrintSDCardInfos();
464
  MUTEX_SDCARD_GIVE;
465
#endif
466
 
467
  out("\n");
468
  out("Reading Root Directory\n");
469
  out("======================\n");
470
 
471
  taskYIELD();
472
 
473
  if( !FILE_SDCardAvailable() ) {
474
    sprintf(str_buffer, "not connected");
475
  } else if( !FILE_VolumeAvailable() ) {
476
    sprintf(str_buffer, "Invalid FAT");
477
  } else {
478
    out("Retrieving SD Card informations - please wait!\n");
479
    MUTEX_MIDIOUT_GIVE;
480
    MUTEX_SDCARD_TAKE;
481
    FILE_UpdateFreeBytes();
482
    MUTEX_SDCARD_GIVE;
483
    MUTEX_MIDIOUT_TAKE;
484
 
485
    sprintf(str_buffer, "'%s': %u of %u MB free",
486
        FILE_VolumeLabel(),
487
        (unsigned int)(FILE_VolumeBytesFree()/1000000),
488
        (unsigned int)(FILE_VolumeBytesTotal()/1000000));
489
  }
490
  out("SD Card: %s\n", str_buffer);
491
 
492
  taskYIELD();
493
 
494
#if _USE_LFN
495
  static char lfn[_MAX_LFN * (_DF1S ? 2 : 1) + 1];
496
  fno.lfname = lfn;
497
  fno.lfsize = sizeof(lfn);
498
#endif
499
 
500
  MUTEX_SDCARD_TAKE;
501
  if( (res=f_opendir(&dir, "/")) != FR_OK ) {
502
    out("Failed to open root directory - error status: %d\n", res);
503
  } else {
504
    while( (f_readdir(&dir, &fno) == FR_OK) && fno.fname[0] ) {
505
#if _USE_LFN
506
      fn = *fno.lfname ? fno.lfname : fno.fname;
507
#else
508
      fn = fno.fname;
509
#endif
510
      char date[10];
511
      ShowFatDate(fno.fdate,(char*)&date);
512
      char time[12];
513
      ShowFatTime(fno.ftime,(char*)&time);
514
      out("[%s%s%s%s%s%s%s] %s  %s   %s %u %s\n",
515
        (fno.fattrib & AM_RDO ) ? "r" : ".",
516
        (fno.fattrib & AM_HID ) ? "h" : ".",
517
        (fno.fattrib & AM_SYS ) ? "s" : ".",
518
        (fno.fattrib & AM_VOL ) ? "v" : ".",
519
        (fno.fattrib & AM_LFN ) ? "l" : ".",
520
        (fno.fattrib & AM_DIR ) ? "d" : ".",
521
        (fno.fattrib & AM_ARC ) ? "a" : ".",
522
        date,time,
523
        (fno.fattrib & AM_DIR) ? "<DIR>" : " ",
524
        fno.fsize,fn);
525
    }
526
  }
527
  MUTEX_SDCARD_GIVE;
528
 
529
  taskYIELD();
530
 
531
  out("done.\n");
532
  MUTEX_MIDIOUT_GIVE;
533
 
534
  return 0; // no error
535
}