Subversion Repositories svn.mios32

Rev

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