123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751 |
- /* tapplay - TAP file playback for sd2iec hardware
- Copyright (C) 2009 Ingo Korb <ingo@akana.de>
- Inspiration and low-level SD/MMC access based on code from MMC2IEC
- by Lars Pontoppidan et al., see sdcard.c|h and config.h.
- FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License only.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- cli.c: The command line interface
- */
- #include <arm/NXP/LPC17xx/LPC17xx.h>
- #include <arm/bits.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <errno.h>
- #include <string.h>
- #include <stdint.h>
- #include <stdlib.h>
- #include "config.h"
- #include "diskio.h"
- #include "ff.h"
- #include "timer.h"
- #include "uart.h"
- #include "fileops.h"
- #include "memory.h"
- #include "snes.h"
- #include "tests.h"
- #include "fpga.h"
- #include "fpga_spi.h"
- #include "cic.h"
- #include "xmodem.h"
- #include "rtc.h"
- #include "cli.h"
- #define MAX_LINE 250
- /* Variables */
- static char cmdbuffer[MAX_LINE + 1];
- static char *curchar;
- /* Word lists */
- static char command_words[] =
- "cd\0reset\0sreset\0dir\0ls\0test\0exit\0loadrom\0loadraw\0saveraw\0put\0rm\0mkdir\0d4\0vmode\0mapper\0settime\0time\0setfeature\0hexdump\0w8\0w16\0memset\0memtest\0";
- enum { CMD_CD = 0, CMD_RESET, CMD_SRESET, CMD_DIR, CMD_LS, CMD_TEST, CMD_EXIT, CMD_LOADROM, CMD_LOADRAW, CMD_SAVERAW, CMD_PUT, CMD_RM, CMD_MKDIR, CMD_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE, CMD_HEXDUMP, CMD_W8, CMD_W16, CMD_MEMSET, CMD_MEMTEST };
- /* ------------------------------------------------------------------------- */
- /* Parse functions */
- /* ------------------------------------------------------------------------- */
- /* Skip spaces at curchar */
- static uint8_t skip_spaces( void )
- {
- uint8_t res = ( *curchar == ' ' || *curchar == 0 );
- while ( *curchar == ' ' )
- {
- curchar++;
- }
- return res;
- }
- /* Parse the string in curchar for an integer with bounds [lower,upper] */
- static int32_t parse_unsigned( uint32_t lower, uint32_t upper, uint8_t base )
- {
- char *end;
- uint32_t result;
- if ( strlen( curchar ) == 1 && *curchar == '?' )
- {
- printf( "Number between %ld[0x%lx] and %ld[0x%lx] expected\n", lower, lower, upper, upper );
- return -2;
- }
- result = strtoul( curchar, &end, base );
- if ( ( *end != ' ' && *end != 0 ) || errno != 0 )
- {
- printf( "Invalid numeric argument\n" );
- return -1;
- }
- curchar = end;
- skip_spaces();
- if ( result < lower || result > upper )
- {
- printf( "Numeric argument out of range (%ld..%ld)\n", lower, upper );
- return -1;
- }
- return result;
- }
- /* Parse the string starting with curchar for a word in wordlist */
- static int8_t parse_wordlist( char *wordlist )
- {
- uint8_t i, matched;
- unsigned char *cur, *ptr;
- unsigned char c;
- i = 0;
- ptr = ( unsigned char * )wordlist;
- // Command list on "?"
- if ( strlen( curchar ) == 1 && *curchar == '?' )
- {
- printf( "Commands available: \n " );
- while ( 1 )
- {
- c = *ptr++;
- if ( c == 0 )
- {
- if ( *ptr == 0 )
- {
- printf( "\n" );
- return -2;
- }
- else
- {
- printf( "\n " );
- }
- }
- else
- {
- uart_putc( c );
- }
- }
- }
- while ( 1 )
- {
- cur = ( unsigned char * )curchar;
- matched = 1;
- c = *ptr;
- do
- {
- // If current word list character is \0: No match found
- if ( c == 0 )
- {
- printf( "Unknown word: %s\n(use ? for help)", curchar );
- return -1;
- }
- if ( tolower( ( int )c ) != tolower( ( int )*cur ) )
- {
- // Check for end-of-word
- if ( cur != ( unsigned char * )curchar && ( *cur == ' ' || *cur == 0 ) )
- {
- // Partial match found, return that
- break;
- }
- else
- {
- matched = 0;
- break;
- }
- }
- ptr++;
- cur++;
- c = *ptr;
- }
- while ( c != 0 );
- if ( matched )
- {
- char *tmp = curchar;
- curchar = ( char * )cur;
- // Return match only if whitespace or end-of-string follows
- // (avoids mismatching partial words)
- if ( skip_spaces() )
- {
- return i;
- }
- else
- {
- printf( "Unknown word: %s\n(use ? for help)\n", tmp );
- return -1;
- }
- }
- else
- {
- // Try next word in list
- i++;
- while ( *ptr++ != 0 ) ;
- }
- }
- }
- /* Read a line from serial, uses cmdbuffer as storage */
- static char *getline( char *prompt )
- {
- int i = 0;
- char c;
- printf( "\n%s", prompt );
- memset( cmdbuffer, 0, sizeof( cmdbuffer ) );
- while ( 1 )
- {
- c = uart_getc();
- if ( c == 13 )
- {
- break;
- }
- if ( c == 27 || c == 3 )
- {
- printf( "\\\n%s", prompt );
- i = 0;
- memset( cmdbuffer, 0, sizeof( cmdbuffer ) );
- continue;
- }
- if ( c == 127 || c == 8 )
- {
- if ( i > 0 )
- {
- i--;
- uart_putc( 8 ); // backspace
- uart_putc( ' ' ); // erase character
- uart_putc( 8 ); // backspace
- }
- else
- {
- continue;
- }
- }
- else
- {
- if ( i < sizeof( cmdbuffer ) - 1 )
- {
- cmdbuffer[i++] = c;
- uart_putc( c );
- }
- }
- }
- cmdbuffer[i] = 0;
- return cmdbuffer;
- }
- /* ------------------------------------------------------------------------- */
- /* Command functions */
- /* ------------------------------------------------------------------------- */
- /* Reset */
- static void cmd_reset( void )
- {
- /* force watchdog reset */
- LPC_WDT->WDTC = 256; // minimal timeout
- LPC_WDT->WDCLKSEL = BV( 31 ); // internal RC, lock register
- LPC_WDT->WDMOD = BV( 0 ) | BV( 1 ); // enable watchdog and reset-by-watchdog
- LPC_WDT->WDFEED = 0xaa;
- LPC_WDT->WDFEED = 0x55; // initial feed to really enable WDT
- }
- /* Show the contents of the current directory */
- static void cmd_show_directory( void )
- {
- FRESULT res;
- DIR dh;
- FILINFO finfo;
- uint8_t *name;
- f_getcwd( ( TCHAR * )file_lfn, 255 );
- res = f_opendir( &dh, ( TCHAR * )file_lfn );
- if ( res != FR_OK )
- {
- printf( "f_opendir failed, result %d\n", res );
- return;
- }
- finfo.lfname = ( TCHAR * )file_lfn;
- finfo.lfsize = 255;
- do
- {
- /* Read the next entry */
- res = f_readdir( &dh, &finfo );
- if ( res != FR_OK )
- {
- printf( "f_readdir failed, result %d\n", res );
- return;
- }
- /* Abort if none was found */
- if ( !finfo.fname[0] )
- {
- break;
- }
- /* Skip volume labels */
- if ( finfo.fattrib & AM_VOL )
- {
- continue;
- }
- /* Select between LFN and 8.3 name */
- if ( finfo.lfname[0] )
- {
- name = ( uint8_t * )finfo.lfname;
- }
- else
- {
- name = ( uint8_t * )finfo.fname;
- strlwr( ( char * )name );
- }
- printf( "%s [%s] (%ld)", finfo.lfname, finfo.fname, finfo.fsize );
- /* Directory indicator (Unix-style) */
- if ( finfo.fattrib & AM_DIR )
- {
- uart_putc( '/' );
- }
- printf( "\n" );
- }
- while ( finfo.fname[0] );
- }
- static void cmd_loadrom( void )
- {
- uint32_t address = 0;
- uint8_t flags = LOADROM_WITH_SRAM | LOADROM_WITH_RESET;
- load_rom( ( uint8_t * )curchar, address, flags );
- }
- static void cmd_loadraw( void )
- {
- uint32_t address = parse_unsigned( 0, 16777216, 16 );
- load_sram( ( uint8_t * )curchar, address );
- }
- static void cmd_saveraw( void )
- {
- uint32_t address = parse_unsigned( 0, 16777216, 16 );
- uint32_t length = parse_unsigned( 0, 16777216, 16 );
- if ( address != -1 && length != -1 )
- {
- save_sram( ( uint8_t * )curchar, length, address );
- }
- }
- static void cmd_d4( void )
- {
- int32_t hz;
- if ( get_cic_state() != CIC_PAIR )
- {
- printf( "not in pair mode\n" );
- }
- else
- {
- hz = parse_unsigned( 50, 60, 10 );
- if ( hz == 50 )
- {
- cic_d4( CIC_PAL );
- }
- else
- {
- cic_d4( CIC_NTSC );
- }
- printf( "ok\n" );
- }
- }
- static void cmd_vmode( void )
- {
- int32_t hz;
- if ( get_cic_state() != CIC_PAIR )
- {
- printf( "not in pair mode\n" );
- }
- else
- {
- hz = parse_unsigned( 50, 60, 10 );
- if ( hz == 50 )
- {
- cic_videomode( CIC_PAL );
- }
- else
- {
- cic_videomode( CIC_NTSC );
- }
- printf( "ok\n" );
- }
- }
- void cmd_put( void )
- {
- if ( *curchar != 0 )
- {
- file_open( ( uint8_t * )curchar, FA_CREATE_ALWAYS | FA_WRITE );
- if ( file_res )
- {
- printf( "FAIL: error opening file %s\n", curchar );
- }
- else
- {
- printf( "OK, start xmodem transfer now.\n" );
- xmodem_rxfile( &file_handle );
- }
- file_close();
- }
- else
- {
- printf( "Usage: put <filename>\n" );
- }
- }
- void cmd_rm( void )
- {
- FRESULT res = f_unlink( curchar );
- if ( res )
- {
- printf( "Error %d removing %s\n", res, curchar );
- }
- }
- void cmd_mkdir( void )
- {
- FRESULT res = f_mkdir( curchar );
- if ( res )
- {
- printf( "Error %d creating directory %s\n", res, curchar );
- }
- }
- void cmd_mapper( void )
- {
- int32_t mapper;
- mapper = parse_unsigned( 0, 7, 10 );
- set_mapper( ( uint8_t )mapper & 0x7 );
- printf( "mapper set to %ld\n", mapper );
- }
- void cmd_sreset( void )
- {
- if ( *curchar != 0 )
- {
- int32_t resetstate;
- resetstate = parse_unsigned( 0, 1, 10 );
- snes_reset( resetstate );
- }
- else
- {
- snes_reset_pulse();
- }
- }
- void cmd_settime( void )
- {
- struct tm time;
- if ( strlen( curchar ) != 4 + 2 + 2 + 2 + 2 + 2 )
- {
- printf( "invalid time format (need YYYYMMDDhhmmss)\n" );
- }
- else
- {
- time.tm_sec = atoi( curchar + 4 + 2 + 2 + 2 + 2 );
- curchar[4 + 2 + 2 + 2 + 2] = 0;
- time.tm_min = atoi( curchar + 4 + 2 + 2 + 2 );
- curchar[4 + 2 + 2 + 2] = 0;
- time.tm_hour = atoi( curchar + 4 + 2 + 2 );
- curchar[4 + 2 + 2] = 0;
- time.tm_mday = atoi( curchar + 4 + 2 );
- curchar[4 + 2] = 0;
- time.tm_mon = atoi( curchar + 4 );
- curchar[4] = 0;
- time.tm_year = atoi( curchar );
- set_rtc( &time );
- }
- }
- void cmd_time( void )
- {
- struct tm time;
- read_rtc( &time );
- printf( "%04d-%02d-%02d %02d:%02d:%02d\n", time.tm_year, time.tm_mon,
- time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec );
- }
- void cmd_setfeature( void )
- {
- uint8_t feat = parse_unsigned( 0, 255, 16 );
- fpga_set_features( feat );
- }
- void cmd_hexdump( void )
- {
- uint32_t offset = parse_unsigned( 0, 16777215, 16 );
- uint32_t len = parse_unsigned( 0, 16777216, 16 );
- sram_hexdump( offset, len );
- }
- void cmd_w8( void )
- {
- uint32_t offset = parse_unsigned( 0, 16777215, 16 );
- uint8_t val = parse_unsigned( 0, 255, 16 );
- sram_writebyte( val, offset );
- }
- void cmd_w16( void )
- {
- uint32_t offset = parse_unsigned( 0, 16777215, 16 );
- uint16_t val = parse_unsigned( 0, 65535, 16 );
- sram_writeshort( val, offset );
- }
- void cmd_memset( void )
- {
- uint32_t offset = parse_unsigned( 0, 16777215, 16 );
- uint32_t len = parse_unsigned( 0, 16777216, 16 );
- uint8_t val = parse_unsigned( 0, 255, 16 );
- sram_memset( offset, len, val );
- }
- /* ------------------------------------------------------------------------- */
- /* CLI interface functions */
- /* ------------------------------------------------------------------------- */
- void cli_init( void )
- {
- }
- void cli_entrycheck()
- {
- if ( uart_gotc() && uart_getc() == 27 )
- {
- printf( "*** BREAK\n" );
- cli_loop();
- }
- }
- void cli_loop( void )
- {
- while ( 1 )
- {
- curchar = getline( ">" );
- printf( "\n" );
- /* Process medium changes before executing the command */
- if ( disk_state != DISK_OK && disk_state != DISK_REMOVED )
- {
- FRESULT res;
- printf( "Medium changed... " );
- res = f_mount( 0, &fatfs );
- if ( res != FR_OK )
- {
- printf( "Failed to mount new medium, result %d\n", res );
- }
- else
- {
- printf( "Ok\n" );
- }
- }
- /* Remove whitespace */
- while ( *curchar == ' ' )
- {
- curchar++;
- }
- while ( strlen( curchar ) > 0 && curchar[strlen( curchar ) - 1] == ' ' )
- {
- curchar[strlen( curchar ) - 1] = 0;
- }
- /* Ignore empty lines */
- if ( strlen( curchar ) == 0 )
- {
- continue;
- }
- /* Parse command */
- int8_t command = parse_wordlist( command_words );
- if ( command < 0 )
- {
- continue;
- }
- FRESULT res;
- switch ( command )
- {
- case CMD_CD:
- #if _FS_RPATH
- if ( strlen( curchar ) == 0 )
- {
- f_getcwd( ( TCHAR * )file_lfn, 255 );
- printf( "%s\n", file_lfn );
- break;
- }
- res = f_chdir( ( const TCHAR * )curchar );
- if ( res != FR_OK )
- {
- printf( "chdir %s failed with result %d\n", curchar, res );
- }
- else
- {
- printf( "Ok.\n" );
- }
- #else
- printf( "cd not supported.\n" );
- res;
- #endif
- break;
- case CMD_RESET:
- cmd_reset();
- break;
- case CMD_SRESET:
- cmd_sreset();
- break;
- case CMD_DIR:
- case CMD_LS:
- cmd_show_directory();
- break;
- case CMD_EXIT:
- return;
- break;
- case CMD_LOADROM:
- cmd_loadrom();
- break;
- case CMD_LOADRAW:
- cmd_loadraw();
- break;
- case CMD_SAVERAW:
- cmd_saveraw();
- break;
- case CMD_RM:
- cmd_rm();
- break;
- case CMD_MKDIR:
- cmd_mkdir();
- break;
- case CMD_D4:
- cmd_d4();
- break;
- case CMD_VMODE:
- cmd_vmode();
- break;
- case CMD_PUT:
- cmd_put();
- break;
- case CMD_MAPPER:
- cmd_mapper();
- break;
- case CMD_SETTIME:
- cmd_settime();
- break;
- case CMD_TIME:
- cmd_time();
- break;
- case CMD_TEST:
- testbattery();
- break;
- case CMD_SETFEATURE:
- cmd_setfeature();
- break;
- case CMD_HEXDUMP:
- cmd_hexdump();
- break;
- case CMD_W8:
- cmd_w8();
- break;
- case CMD_W16:
- cmd_w16();
- break;
- case CMD_MEMSET:
- cmd_memset();
- break;
- case CMD_MEMTEST:
- test_mem();
- break;
- }
- }
- }
|