cic interface, cli for real this time...
This commit is contained in:
parent
46a42fe5ac
commit
d4b7d9630b
73
src/cic.c
Normal file
73
src/cic.c
Normal file
@ -0,0 +1,73 @@
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include "bits.h"
|
||||
#include "config.h"
|
||||
#include "uart.h"
|
||||
#include "cic.h"
|
||||
|
||||
char *cicstatenames[3] = { "CIC_OK", "CIC_FAIL", "CIC_PAIR" };
|
||||
|
||||
void print_cic_state() {
|
||||
printf("CIC state: %s\n", get_cic_statename(get_cic_state()));
|
||||
}
|
||||
|
||||
inline char *get_cic_statename(enum cicstates state) {
|
||||
return cicstatenames[state];
|
||||
}
|
||||
|
||||
enum cicstates get_cic_state() {
|
||||
uint32_t count;
|
||||
uint32_t togglecount = 0;
|
||||
uint8_t state, state_old;
|
||||
|
||||
state_old = BITBAND(SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT);
|
||||
for(count=0; count<1000; count++) {
|
||||
state = BITBAND(SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT);
|
||||
if(state != state_old) {
|
||||
togglecount++;
|
||||
}
|
||||
state_old = state;
|
||||
}
|
||||
if(togglecount > 20) {
|
||||
printf("%ld\n", togglecount);
|
||||
return CIC_PAIR;
|
||||
}
|
||||
if(state) {
|
||||
return CIC_OK;
|
||||
}
|
||||
return CIC_FAIL;
|
||||
}
|
||||
|
||||
void cic_init(int allow_pairmode) {
|
||||
BITBAND(SNES_CIC_PAIR_REG->FIODIR, SNES_CIC_PAIR_BIT) = 1;
|
||||
if(allow_pairmode) {
|
||||
BITBAND(SNES_CIC_PAIR_REG->FIOCLR, SNES_CIC_PAIR_BIT) = 1;
|
||||
} else {
|
||||
BITBAND(SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* prepare GPIOs for pair mode + set initial modes */
|
||||
void cic_pair(int init_vmode, int init_d4) {
|
||||
cic_videomode(init_vmode);
|
||||
cic_d4(init_d4);
|
||||
|
||||
BITBAND(SNES_CIC_D0_REG->FIODIR, SNES_CIC_D0_BIT) = 1;
|
||||
BITBAND(SNES_CIC_D1_REG->FIODIR, SNES_CIC_D1_BIT) = 1;
|
||||
}
|
||||
|
||||
void cic_videomode(int value) {
|
||||
if(value) {
|
||||
BITBAND(SNES_CIC_D0_REG->FIOSET, SNES_CIC_D0_BIT) = 1;
|
||||
} else {
|
||||
BITBAND(SNES_CIC_D0_REG->FIOCLR, SNES_CIC_D0_BIT) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void cic_d4(int value) {
|
||||
if(value) {
|
||||
BITBAND(SNES_CIC_D1_REG->FIOSET, SNES_CIC_D1_BIT) = 1;
|
||||
} else {
|
||||
BITBAND(SNES_CIC_D1_REG->FIOCLR, SNES_CIC_D1_BIT) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
19
src/cic.h
Normal file
19
src/cic.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef _CIC_H
|
||||
#define _CIC_H
|
||||
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include "bits.h"
|
||||
|
||||
enum cicstates { CIC_OK = 0, CIC_FAIL, CIC_PAIR };
|
||||
enum cic_region { CIC_NTSC = 0, CIC_PAL };
|
||||
|
||||
void print_cic_state(void);
|
||||
char *get_cic_statename(enum cicstates state);
|
||||
enum cicstates get_cic_state(void);
|
||||
void cic_init(int allow_pairmode);
|
||||
|
||||
void cic_pair(int init_vmode, int init_d4);
|
||||
void cic_videomode(int value);
|
||||
void cic_d4(int value);
|
||||
|
||||
#endif
|
||||
440
src/cli.c
Normal file
440
src/cli.c
Normal file
@ -0,0 +1,440 @@
|
||||
/* 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 "cic.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\0dir\0ls\0test\0resume\0loadrom\0loadraw\0put\0d4\0vmode\0";
|
||||
enum { CMD_CD = 0, CMD_RESET, CMD_DIR, CMD_LS, CMD_TEST, CMD_RESUME, CMD_LOADROM, CMD_LOADRAW, CMD_PUT, CMD_D4, CMD_VMODE };
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* 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);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (finfo.fattrib & AM_DIR) {
|
||||
printf("DIR ");
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
snes_reset(1);
|
||||
set_mcu_ovr(1);
|
||||
load_rom((uint8_t*)curchar, address);
|
||||
set_mcu_ovr(0);
|
||||
snes_reset(0);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
uint8_t *buf = malloc(256);
|
||||
|
||||
if (buf == NULL) {
|
||||
printf("buffer allocation failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=0;i<256;i++) {
|
||||
buf[i] = i2c_read_register(0xa0, i);
|
||||
}
|
||||
|
||||
uart_trace(buf, 0, 256);
|
||||
free(buf);
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* 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_DIR:
|
||||
case CMD_LS:
|
||||
cmd_show_directory();
|
||||
break;
|
||||
|
||||
case CMD_RESUME:
|
||||
return;
|
||||
break;
|
||||
|
||||
case CMD_LOADROM:
|
||||
cmd_loadrom();
|
||||
break;
|
||||
|
||||
case CMD_D4:
|
||||
cmd_d4();
|
||||
break;
|
||||
|
||||
case CMD_VMODE:
|
||||
cmd_vmode();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
34
src/cli.h
Normal file
34
src/cli.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* 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.h: Definitions for cli.c
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CLI_H
|
||||
#define CLI_H
|
||||
|
||||
void cli_init(void);
|
||||
void cli_loop(void);
|
||||
void cli_entrycheck(void);
|
||||
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user