123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- /* 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 "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\0resume\0loadrom\0loadraw\0saveraw\0put\0d4\0vmode\0mapper\0settime\0time\0setfeature\0";
- enum { CMD_CD = 0, CMD_RESET, CMD_SRESET, CMD_DIR, CMD_LS, CMD_TEST, CMD_RESUME, CMD_LOADROM, CMD_LOADRAW, CMD_SAVERAW, CMD_PUT, CMD_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE };
- /* ------------------------------------------------------------------------- */
- /* 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) {
- 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, 10);
- 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;
- char *cur, *ptr;
- char c;
- i = 0;
- ptr = 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 = curchar;
- matched = 1;
- c = *ptr;
- do {
- // If current word list character is \0: No match found
- if (c == 0) {
- printf("Unknown word: %s\n",curchar);
- return -1;
- }
- if (tolower(c) != tolower(*cur)) {
- // Check for end-of-word
- if (cur != 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 = 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",name);
- /* 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;
- set_mcu_ovr(1);
- load_rom((uint8_t*)curchar, address, flags);
- set_mcu_ovr(0);
- }
- static void cmd_saveraw(void) {
- uint32_t address = parse_unsigned(0,16777216);
- uint32_t length = parse_unsigned(0,16777216);
- set_mcu_ovr(0);
- 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);
- 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);
- 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_mapper(void) {
- int32_t mapper;
- mapper = parse_unsigned(0,7);
- 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);
- snes_reset(resetstate);
- } else {
- snes_reset(1);
- delay_ms(20);
- snes_reset(0);
- }
- }
- 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);
- fpga_set_features(feat);
- }
- /* ------------------------------------------------------------------------- */
- /* 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_RESUME:
- return;
- break;
- case CMD_LOADROM:
- cmd_loadrom();
- break;
- case CMD_SAVERAW:
- cmd_saveraw();
- 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;
- }
- }
- }
|