summaryrefslogtreecommitdiff
path: root/avr
diff options
context:
space:
mode:
authorLeo C2015-06-11 17:43:28 +0200
committerLeo C2015-06-11 17:43:28 +0200
commit1157e75889d3d6d23d1e2514f401cd5b354bd149 (patch)
treeedad2bcaddaec49a18a1b4bac2b813ce9e5a36bf /avr
parent8506d791786eea8ee55db5418a8f646bb2dd3a6d (diff)
parent057817cb1dc71416bc798b5cd592acfcea87efaa (diff)
downloadz180-stamp-1157e75889d3d6d23d1e2514f401cd5b354bd149.zip
Merge branch 'master' into cmdline_edit
Diffstat (limited to 'avr')
-rw-r--r--avr/Tupfile32
-rw-r--r--avr/background.c16
-rw-r--r--avr/bcd.c21
-rw-r--r--avr/cli.c133
-rw-r--r--avr/cli_readline.c13
-rw-r--r--avr/cmd_boot.c69
-rw-r--r--avr/cmd_date.c136
-rw-r--r--avr/cmd_fat.c419
-rw-r--r--avr/cmd_gpio.c8
-rw-r--r--avr/cmd_help.c8
-rw-r--r--avr/cmd_loadcpm3.c172
-rw-r--r--avr/cmd_loadihex.c261
-rw-r--r--avr/cmd_mem.c377
-rw-r--r--avr/cmd_misc.c48
-rw-r--r--avr/cmd_sd.c81
-rw-r--r--avr/command.c15
-rw-r--r--avr/command_tbl.c105
-rw-r--r--avr/con-utils.c34
-rw-r--r--avr/date.c139
-rw-r--r--avr/debug.c108
-rw-r--r--avr/env.c46
-rw-r--r--avr/getopt-min.c9
-rw-r--r--avr/gpio.c62
-rw-r--r--avr/i2c.c8
-rw-r--r--avr/main.c80
-rw-r--r--avr/mmc.c218
-rw-r--r--avr/pcf8583.c27
-rw-r--r--avr/print-utils.c13
-rw-r--r--avr/serial.c9
-rw-r--r--avr/timer.c23
-rw-r--r--avr/xmalloc.c11
-rw-r--r--avr/z180-serv.c455
-rw-r--r--avr/z180-stamp-avr.c591
-rw-r--r--avr/z80-if.c12
34 files changed, 2189 insertions, 1570 deletions
diff --git a/avr/Tupfile b/avr/Tupfile
index 11b5802..d73db12 100644
--- a/avr/Tupfile
+++ b/avr/Tupfile
@@ -1,14 +1,25 @@
include_rules
PROG = stamp-monitor
+
+FATFS = $(TOP)/fatfs/src/ff.c
+
SRC = main.c
SRC += cli.c cli_readline.c command.c command_tbl.c
SRC += cmd_help.c cmd_date.c cmd_mem.c cmd_boot.c cmd_gpio.c cmd_misc.c
-SRC += cmd_sd.c cmd_fat.c
-SRC += env.c xmalloc.c date.c con-utils.c print-utils.c getopt-min.c
-SRC += timer.c serial.c i2c.c pcf8583.c mmc.c
+SRC += cmd_loadihex.c cmd_loadcpm3.c cmd_sd.c cmd_fat.c
+SRC += env.c xmalloc.c con-utils.c print-utils.c getopt-min.c
+SRC += timer.c serial.c i2c.c bcd.c pcf8583.c mmc.c
SRC += background.c z180-serv.c z80-if.c gpio.c
-SRC += $(TOP)/fatfs/src/ff.c
+SRC += $(FATFS) $(TOP)/fatfs/src/option/unicode.c
+
+#TODO: time lib
+SRC += ../time/asctime_r.c ../time/gmtime_r.c ../time/mk_gmtime.c
+SRC += ../time/print_lz.c ../time/isLeap.c
+SRC += ../time/time.c ../time/fatfs_time.c
+SRC += ../time/system_time.c ../time/set_system_time.c
+
+ASRC += ../time/system_tick.S
SRC_Z = ../z180/hdrom.c
@@ -59,25 +70,34 @@ CFLAGS += -fno-split-wide-types
CFLAGS += -fshort-enums
#CFLAGS += -fdiagnostics-color=always
-
#CFLAGS += -save-temps
+CFLAGS_$(FATFS) = -fno-strict-aliasing
CFLAGS += $(INCLUDES)
CPPFLAGS += $(DEFS)
+#ASFLAGS += -Wa,-adhlns=$(<:.S=.lst),-gstabs
+ASFLAGS += -mmcu=$(MCU_TARGET) -x assembler-with-cpp $(ASFLAGS)
+
# Linker flags
LDFLAGS += -Wl,--gc-sections
LDFLAGS += -Wl,--cref
+# Assemble: create object files from assembler source files.
+#.S.o:
+# $(CC) -c $(ALL_ASFLAGS) $< -o $@
+
-!cc = |> ^ CC %f^ $(CC) $(CFLAGS) $(CPPFLAGS) -c %f -o %o |> %B.o
+!as = |> ^ AS %f^ $(CC) $(ASFLAGS) -c %f -o %o |> %B.o
+!cc = |> ^ CC %f^ $(CC) $(CFLAGS) $(CPPFLAGS) $(CFLAGS_%f) -c %f -o %o |> %B.o
!LINK = |> ^ LINK %o^ $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-Map=%O.map %f $(LDLIBS) -o %o |> | %O.map
!OBJCOPY= |> ^ OBJCOPY %o^ $(OBJCOPY) -Oihex %f %o |>
!OBJDUMP= |> ^ OBJDUMP %o^ $(OBJDUMP) -h -S %f > %o |> %O.lss
!SIZE = |> ^ SIZE^ $(SIZE) %f |>
+: foreach $(ASRC) |> !as |> {objs}
: foreach $(SRC) | ../z180/hdrom.h |> !cc |> {objs}
: $(SRC_Z) |> !cc -D'const=const __flash' |> {objs}
diff --git a/avr/background.c b/avr/background.c
index 0e1ca40..9c8b5a6 100644
--- a/avr/background.c
+++ b/avr/background.c
@@ -1,10 +1,16 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
#include "common.h"
#include "background.h"
#define BG_FUNC_MAX 5
-static struct {
+static struct {
bg_func fct;
int param;
} func_tab[BG_FUNC_MAX];
@@ -13,7 +19,7 @@ static int_fast8_t fcount;
int bg_register(bg_func f, int initval)
{
- if (fcount < BG_FUNC_MAX) {
+ if (fcount < BG_FUNC_MAX) {
func_tab[fcount].fct = f;
func_tab[fcount].param = initval;
return ++fcount - 1;
@@ -27,7 +33,7 @@ int bg_setstat(int handle, int val)
func_tab[handle].param = val;
return 1;
}
-
+
return 0;
}
@@ -44,7 +50,7 @@ int bg_getstat(int handle)
void bg_shed(void)
{
static int_fast8_t current;
-
+
if (func_tab[current].fct) {
int v = func_tab[current].fct(func_tab[current].param);
func_tab[current].param = v;
@@ -52,5 +58,3 @@ void bg_shed(void)
if (++current >= fcount)
current = 0;
}
-
-
diff --git a/avr/bcd.c b/avr/bcd.c
new file mode 100644
index 0000000..5154852
--- /dev/null
+++ b/avr/bcd.c
@@ -0,0 +1,21 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "stdlib.h"
+#include "stdint.h"
+#include "bcd.h"
+
+uint_fast8_t bcd2bin(uint8_t val)
+{
+ return (val >> 4) * 10 + (val & 0x0f);
+}
+
+uint8_t bin2bcd (uint_fast8_t val)
+{
+ div_t d = div(val, 10);
+
+ return (d.quot << 4) | d.rem;
+}
diff --git a/avr/cli.c b/avr/cli.c
index b310f79..43b5be0 100644
--- a/avr/cli.c
+++ b/avr/cli.c
@@ -1,3 +1,16 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Add to readline cmdline-editing by
+ * (C) Copyright 2005
+ * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
#include "common.h"
#include <string.h>
@@ -14,6 +27,9 @@
#include "con-utils.h"
#include "cli.h"
+
+/* FIXME: Quoting problems */
+
#define DEBUG_PARSER 0 /* set to 1 to debug */
#define debug_parser(fmt, args...) \
@@ -21,26 +37,75 @@
static int cli_parse_line(char *line, char *argv[])
{
- static const FLASH char delim[] = {" \t"};
-
- char *ptr;
+ uint_fast8_t state = 0;
uint_fast8_t nargs = 0;
+ char *inp, *outp;
+ char c, quote;
- debug_parser("parse_line: \"%s\"\n", line);
+ debug_parser("%s: \"%s\"\n", __func__, line);
+
+ for (outp = inp = line, quote = '\0' ;
+ nargs < CONFIG_SYS_MAXARGS && (c = *inp) != '\0';
+ inp++) {
+
+ switch (state) {
+ case 0: /* before arg string, waiting for arg start */
+ if (isblank(c))
+ continue;
+
+ argv[nargs++] = inp; /* begin of argument string */
+ outp = inp;
+ state = 1;
+ /* fall thru */
+
+ case 1: /* in arg string, waiting for end of arg string */
+ if (c == '\\') {
+ ++state;
+ continue;
+ }
+ if (c == '\"' || c == '\'') {
+ quote = c;
+ state = 3;
+ continue;
+ }
+ if (isblank(c)) {
+ c = '\0';
+ state = 0;
+ }
+ break;
- ptr = strtok_P(line, delim);
- while(nargs < CONFIG_SYS_MAXARGS && ptr != NULL) {
- argv[nargs++] = ptr;
- ptr = strtok_P(NULL, delim);
+ case 3: /* in quote */
+ if (c == '\\' && quote == '\"') {
+ ++state;
+ continue;
+ }
+ if (c == quote) {
+ state = 1;
+ continue;
+ }
+ break;
+
+ case 2: /* waiting for next char */
+ case 4:
+ --state;
+ break;
+
+ }
+ *outp++ = c;
}
- if (ptr != NULL)
+ if (*inp != '\0')
printf_P(PSTR("** Too many args (max. %d) **\n"), CONFIG_SYS_MAXARGS);
+ *outp = '\0';
argv[nargs] = NULL;
- debug_parser("parse_line: nargs=%d\n", nargs);
-
+ debug_parser("%s: nargs=%d\n", __func__, nargs);
+#if 0
+ for (int i = 0; i < nargs; i++)
+ debug_parser("%s: arg %d: >%s<\n", __func__, i, argv[i]);
+#endif
return nargs;
+
}
static
@@ -61,7 +126,8 @@ char *process_macros(char *input, char *output)
for(uint_fast8_t pass = 0; pass < 2; pass++)
{
- uint_fast8_t state = 0; /* 0 = waiting for '$' */
+ uint_fast8_t state = 0;
+ /* 0 = waiting for '$' */
/* 1 = waiting for '{' */
/* 2 = waiting for '}' */
/* 3 = waiting for ''' */
@@ -75,22 +141,13 @@ char *process_macros(char *input, char *output)
}
inp = input;
- prev = '\0'; /* previous character */
- debug_parser("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(inp),
- inp);
+ debug_parser("[PROCESS_MACROS] INPUT len %d: \"%s\"\n",
+ strlen(inp), inp);
+
+ for (prev = '\0'; (c = *inp++) != '\0'; prev = c) {
- while ((c = *inp++) != '\0') {
- if (state != 3) {
- /* remove one level of escape characters */
- if ((c == '\\') && (prev != '\\')) {
- if (*inp == '\0')
- break;
- prev = c;
- c = *inp++;
- }
- }
switch (state) {
case 0: /* Waiting for (unescaped) $ */
@@ -98,19 +155,19 @@ char *process_macros(char *input, char *output)
state = 3;
break;
}
- if ((c == '$') && (prev != '\\'))
+ if ((c == '$') && (prev != '\\')) {
state++;
- else
- append_char(pass, &outp, c);
+ continue;
+ }
break;
case 1: /* Waiting for { */
if (c == '{') {
state++;
varname = inp;
+ continue;
} else {
state = 0;
append_char(pass, &outp, '$');
- append_char(pass, &outp, c);
}
break;
case 2: /* Waiting for } */
@@ -126,15 +183,13 @@ char *process_macros(char *input, char *output)
/* Look for another '$' */
state = 0;
}
- break;
+ continue;
case 3: /* Waiting for ' */
- if ((c == '\'') && (prev != '\\'))
+ if (c == '\'')
state = 0;
- else
- append_char(pass, &outp, c);
break;
}
- prev = c;
+ append_char(pass, &outp, c);
}
append_char(pass, &outp, 0);
@@ -200,12 +255,13 @@ static int cli_run_command(const char *cmd, int flag)
*/
for (inquotes = 0, sep = str; *sep; sep++) {
if ((*sep == '\'') &&
- (*(sep - 1) != '\\'))
+ (sep != str) && /* past string start */
+ (*(sep - 1) != '\\')) /* and NOT escaped */
inquotes = !inquotes;
if (!inquotes &&
- (*sep == ';' || *sep == '\n') && /* separator */
- (sep != str) && /* past string start */
+ (*sep == ';' || *sep == '\n') && /* separator */
+ (sep != str) && /* past string start */
(*(sep - 1) != '\\')) /* and NOT escaped */
break;
}
@@ -257,7 +313,7 @@ static int cli_run_command_list(const char *cmd)
/*
- * Run a command using the selected parser.
+ * Run a command.
*
* @param cmd Command to run
* @param flag Execution flags (CMD_FLAG_...)
@@ -350,4 +406,3 @@ command_ret_t do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
return CMD_RET_SUCCESS;
}
-
diff --git a/avr/cli_readline.c b/avr/cli_readline.c
index 8795a97..ff83a3a 100644
--- a/avr/cli_readline.c
+++ b/avr/cli_readline.c
@@ -1,4 +1,6 @@
/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
@@ -10,7 +12,6 @@
*/
#include "common.h"
-
#include <string.h>
#include <stdio.h>
#include <ctype.h>
@@ -666,16 +667,8 @@ static int cli_readline_into_buffer(const FLASH char *const prompt, char *buffer
my_puts_P(tab_seq + (col & 07));
col += 8 - (col & 07);
} else {
- char buf[2];
-
- /*
- * Echo input using puts() to force an
- * LCD flush if we are using an LCD
- */
++col;
- buf[0] = c;
- buf[1] = '\0';
- my_puts(buf);
+ putchar(c);
}
*p++ = c;
++n;
diff --git a/avr/cmd_boot.c b/avr/cmd_boot.c
index 4775b6e..b8799aa 100644
--- a/avr/cmd_boot.c
+++ b/avr/cmd_boot.c
@@ -1,3 +1,11 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
/*
* Misc boot support
@@ -8,6 +16,9 @@
#include <util/atomic.h>
#include "command.h"
+#include "cli_readline.h"
+#include "cli.h"
+#include "env.h"
#include "con-utils.h"
#include "z80-if.h"
#include "z180-serv.h"
@@ -33,11 +44,9 @@ static void z80_load_mem(void)
hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
hdrom_length_of_sections[sec]);
- z80_bus_cmd(Request);
z80_write_block_P((const FLASH unsigned char *) &hdrom[sec_base], /* src */
hdrom_address[sec], /* dest */
hdrom_length_of_sections[sec]); /* len */
- z80_bus_cmd(Release);
sec_base+=hdrom_length_of_sections[sec];
sec++;
}
@@ -48,11 +57,15 @@ command_ret_t do_loadf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
(void) cmdtp; (void) flag; (void) argc; (void) argv;
if (z80_bus_state() & ZST_RUNNING) {
- printf_P(PSTR("## Can't load while CPU is running!\n"));
+ my_puts_P(PSTR("Can't load while CPU is running!\n"));
return CMD_RET_FAILURE;
}
-
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ my_puts_P(PSTR("Bus timeout\n"));
+ return CMD_RET_FAILURE;
+ }
z80_load_mem();
+ z80_bus_cmd(Release);
return CMD_RET_SUCCESS;
}
@@ -139,7 +152,7 @@ command_ret_t do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
{
(void) cmdtp; (void) flag; (void) argc; (void) argv;
- printf_P(PSTR("## CPU now in reset state.\n"));
+ printf_P(PSTR("CPU now in reset state.\n"));
reset_cpu(Reset);
return CMD_RET_SUCCESS;
@@ -159,12 +172,13 @@ void print_con_usage(char esc)
{ printf_P(PSTR("\n"
"------------------------------------------------\n"
" ?,H - This Help\n"
- " R - Reset (Restart) CPU\n"
" Q,X - Return to command line\n"
- " \\ - code input:\n"
- " \\nnn 3 decimal digits character code\n"
- " \\Xhh 2 hexadecimal digits character code\n"
- " ^%c - (Escape char) Type again to send itself\n"
+ " R - Reset (Restart) CPU\n"
+ " : - Execute monitor command\n"
+ " \\ - code input:\n"
+ " \\nnn 3 decimal digits character code\n"
+ " \\Xhh 2 hexadecimal digits character code\n"
+ " ^%c - (Escape char) Type again to send itself\n"
"key>"
), esc + 0x40);
}
@@ -176,9 +190,12 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
// uint8_t help_prompt = 0;
uint8_t code = 0;
uint8_t state = 0;
+ char esc_char = (char) getenv_ulong(PSTR(ENV_ESC_CHAR), 16, CONFIG_ESC_CHAR);
(void) cmdtp; (void) flag; (void) argc; (void) argv;
+ printf_P(PSTR("Connecting to CPU. Escape character is '^%c'.\n"),
+ esc_char + 0x40);
while (1) {
@@ -186,14 +203,16 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
pending = (Stat & S_CON_PENDING) != 0;
Stat &= ~S_CON_PENDING;
}
- if (pending)
- while ((ch = z80_memfifo_getc(fifo_conout)) >= 0)
+ if (pending) {
+ uint8_t count = 100;
+ while ((ch = z80_memfifo_getc(fifo_conout)) >= 0 && --count)
putchar(ch);
+ }
if ((ch = my_getchar(0)) >= 0) {
switch (state) {
case 0:
- if (ch == CONFIG_ESC_CHAR) {
+ if (ch == esc_char) {
state = 1;
/* TODO: Timer starten */
} else {
@@ -209,7 +228,7 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
case '?':
case 'H':
- print_con_usage(CONFIG_ESC_CHAR);
+ print_con_usage(esc_char);
state = 2;
break;
@@ -223,15 +242,21 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
goto quit;
break;
+ case ':':
+ putchar('\n');
+ int cmdlen = cli_readline(PSTR(": "));
+ if (cmdlen > 0)
+ run_command(console_buffer, 0);
+ break;
+
case '\\':
code = 0;
state = 3;
break;
- case CONFIG_ESC_CHAR:
- z80_memfifo_putc(fifo_conin, ch);
- break;
default:
+ if (ch == esc_char)
+ z80_memfifo_putc(fifo_conin, ch);
break;
}
break;
@@ -246,6 +271,11 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
if (isdigit(ch)) {
code = code * 10 + ch - '0';
state++;
+ } else {
+ if (state > 3)
+ z80_memfifo_putc(fifo_conin, code);
+ z80_memfifo_putc(fifo_conin, ch);
+ state = 0;
}
if (state > 5) {
z80_memfifo_putc(fifo_conin, code);
@@ -260,6 +290,11 @@ command_ret_t do_console(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
ch -= 'A' - 10;
code = code * 16 + ch - '0';
state++;
+ }else {
+ if (state > 6)
+ z80_memfifo_putc(fifo_conin, code);
+ z80_memfifo_putc(fifo_conin, ch);
+ state = 0;
}
if (state > 7) {
z80_memfifo_putc(fifo_conin, code);
diff --git a/avr/cmd_date.c b/avr/cmd_date.c
index ad0d3ac..efba858 100644
--- a/avr/cmd_date.c
+++ b/avr/cmd_date.c
@@ -1,4 +1,6 @@
/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
* (C) Copyright 2001
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
@@ -8,66 +10,12 @@
/*
* RTC, Date & Time support: get and set date & time
*/
-#include <common.h>
+#include "common.h"
#include <string.h>
-#include <command.h>
-#include <rtc.h>
-#include <i2c.h>
-
-
-static const char * const weekdays[] = {
- "Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur",
-};
-
-int mk_date (const char *, struct rtc_time *);
-
-command_ret_t do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- struct rtc_time tm;
- int rcode = CMD_RET_SUCCESS;
-
- (void) cmdtp; (void) flag;
-
- switch (argc) {
- case 2: /* set date & time */
- /* initialize tm with current time */
- rcode = rtc_get (&tm);
-
- if(!rcode) {
- /* insert new date & time */
- if (mk_date (argv[1], &tm) != 0) {
- my_puts_P(PSTR("## Bad date format\n"));
- break;
- }
- /* and write to RTC */
- rcode = rtc_set (&tm);
- if(rcode)
- my_puts_P(PSTR("## Set date failed\n"));
- } else {
- my_puts_P(PSTR("## Get date failed\n"));
- }
- /* FALL TROUGH */
- case 1: /* get date & time */
- rcode = rtc_get (&tm);
+#include "time.h"
+#include "rtc.h"
+#include "command.h"
- if (rcode) {
- my_puts_P(PSTR("## Get date failed\n"));
- break;
- }
- /* TODO: put weekdays[] in flash */
- printf_P(PSTR("Date: %4d-%02d-%02d (%sday) Time: %2d:%02d:%02d\n"),
- tm.tm_year, tm.tm_mon, tm.tm_mday,
- (tm.tm_wday<0 || tm.tm_wday>6) ?
- "unknown " : weekdays[tm.tm_wday],
- tm.tm_hour, tm.tm_min, tm.tm_sec);
-
- break;
- default:
- rcode = CMD_RET_USAGE;
- }
-
- return rcode;
-}
/*
* simple conversion of two-digit string with error checking
@@ -97,7 +45,7 @@ static int cnvrt2 (const char *str, int *valp)
* Some basic checking for valid values is done, but this will not catch
* all possible error conditions.
*/
-int mk_date (const char *datestr, struct rtc_time *tmp)
+int mk_date (const char *datestr, struct tm *tmp)
{
int len, val;
char *ptr;
@@ -123,36 +71,36 @@ int mk_date (const char *datestr, struct rtc_time *tmp)
tmp->tm_sec = 0;
}
- if (len == 12) { /* MMDDhhmmCCYY */
+ if (len == 12) { /* MMDDhhmmCCYY */
int year, century;
if (cnvrt2 (datestr+ 8, &century) ||
cnvrt2 (datestr+10, &year) ) {
return (-1);
}
- tmp->tm_year = 100 * century + year;
+ tmp->tm_year = 100 * century + year - 1900;
} else if (len == 10) { /* MMDDhhmmYY */
int year, century;
- century = tmp->tm_year / 100;
+ century = (tmp->tm_year + 1900) / 100;
if (cnvrt2 (datestr+ 8, &year))
return (-1);
- tmp->tm_year = 100 * century + year;
+ tmp->tm_year = 100 * century + year -1900;
}
switch (len) {
- case 8: /* MMDDhhmm */
+ case 8: /* MMDDhhmm */
/* fall thru */
- case 10: /* MMDDhhmmYY */
+ case 10: /* MMDDhhmmYY */
/* fall thru */
- case 12: /* MMDDhhmmCCYY */
+ case 12: /* MMDDhhmmCCYY */
if (cnvrt2 (datestr+0, &val) ||
val > 12) {
break;
}
- tmp->tm_mon = val;
+ tmp->tm_mon = val - 1;
if (cnvrt2 (datestr+2, &val) ||
- val > ((tmp->tm_mon==2) ? 29 : 31)) {
+ val > ((tmp->tm_mon==2-1) ? 29 : 31)) {
break;
}
tmp->tm_mday = val;
@@ -169,9 +117,6 @@ int mk_date (const char *datestr, struct rtc_time *tmp)
}
tmp->tm_min = val;
- /* calculate day of week */
- GregorianDay (tmp);
-
return (0);
default:
break;
@@ -180,3 +125,52 @@ int mk_date (const char *datestr, struct rtc_time *tmp)
return (-1);
}
+command_ret_t do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ struct tm t;
+ char buf[30];
+ int rcode = CMD_RET_SUCCESS;
+
+ (void) cmdtp; (void) flag;
+
+ switch (argc) {
+ case 2: /* set date & time */
+ /* initialize t with current time */
+ rcode = rtc_get (&t);
+
+ if(!rcode) {
+ /* insert new date & time */
+ if (mk_date (argv[1], &t) != 0) {
+ my_puts_P(PSTR("## Bad date format\n"));
+ break;
+ }
+
+ time_t time;
+ time = mk_gmtime(&t);
+ gmtime_r(&time, &t);
+
+ /* and write to RTC */
+ rcode = rtc_set (&t);
+ if(rcode)
+ my_puts_P(PSTR("## Set date failed\n"));
+ } else {
+ my_puts_P(PSTR("## Get date failed\n"));
+ }
+ /* FALL TROUGH */
+ case 1: /* get date & time */
+ rcode = rtc_get (&t);
+
+ if (rcode) {
+ my_puts_P(PSTR("## Get date failed\n"));
+ break;
+ }
+ asctime_r(&t, buf);
+ printf_P(PSTR("%s\n"), buf);
+ break;
+
+ default:
+ rcode = CMD_RET_USAGE;
+ }
+
+ return rcode;
+}
diff --git a/avr/cmd_fat.c b/avr/cmd_fat.c
index 9222c1b..af2f772 100644
--- a/avr/cmd_fat.c
+++ b/avr/cmd_fat.c
@@ -1,3 +1,13 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * FAT filesystem commands
+ */
+
#include "common.h"
#include <stdlib.h>
#include <string.h>
@@ -6,13 +16,37 @@
#include "command.h"
#include "ff.h"
#include "z80-if.h"
+#include "con-utils.h"
#include "print-utils.h"
+#include "time.h"
#include "timer.h"
+#include "debug.h"
+
+/* TODO: use memory size test function (cmd_mem.c) */
+#define MAX_MEMORY (1ul << 19)
+#define BUFFER_SIZE 512
DWORD get_fattime (void)
{
- return 0;
+ time_t timer;
+ struct tm tm_timer;
+
+ time(&timer);
+ gmtime_r(&timer, &tm_timer);
+
+ return fatfs_time(&tm_timer);
+}
+
+
+static bool check_abort(void)
+{
+ bool ret = ctrlc();
+
+ if (ret)
+ printf_P(PSTR("Abort\n"));
+
+ return ret;
}
@@ -41,23 +75,42 @@ static const FLASH char * const FLASH rc_names[] = {
static
void put_rc (FRESULT rc)
{
+ if (rc < ARRAY_SIZE(rc_names)) {
#if GCC_BUG_61443
- printf_P(PSTR("rc=%u FR_"), rc);
- my_puts_P(rc_names[rc]);
- my_puts_P(PSTR("\n"));
+ printf_P(PSTR("rc=%u FR_"), rc);
+ my_puts_P(rc_names[rc]);
+ my_puts_P(PSTR("\n"));
#else
- printf_P(PSTR("rc=%u FR_%S\n"), rc, rc_names[rc]);
+ printf_P(PSTR("rc=%u FR_%S\n"), rc, rc_names[rc]);
#endif
+ }
+}
+
+
+static void swirl(void)
+{
+ static const FLASH char swirlchar[] = { '-','\\','|','/' };
+ static uint_fast8_t cnt;
+ static uint32_t tstamp;
+
+ if (get_timer(0) > tstamp) {
+ printf_P(PSTR("\b%c"), swirlchar[cnt]);
+ cnt = (cnt+1) % ARRAY_SIZE(swirlchar);
+ tstamp = get_timer(0) + 250;
+ }
}
/* Work register for fs command */
-static DWORD AccSize;
-static WORD AccFiles, AccDirs;
-FILINFO Finfo;
+struct stat_dat_s {
+ DWORD AccSize;
+ WORD AccFiles, AccDirs;
+ FILINFO Finfo;
+};
static
FRESULT scan_files (
- char* path /* Pointer to the working buffer with start path */
+ char *path, /* Pointer to the working buffer with start path */
+ struct stat_dat_s *statp
)
{
DIR dirs;
@@ -66,25 +119,30 @@ FRESULT scan_files (
char *fn;
res = f_opendir(&dirs, path);
+ swirl();
if (res == FR_OK) {
i = strlen(path);
- while (((res = f_readdir(&dirs, &Finfo)) == FR_OK) && Finfo.fname[0]) {
- if (_FS_RPATH && Finfo.fname[0] == '.') continue;
-#if _USE_LFN
- fn = *Finfo.lfname ? Finfo.lfname : Finfo.fname;
-#else
- fn = Finfo.fname;
-#endif
- if (Finfo.fattrib & AM_DIR) {
- AccDirs++;
- path[i] = '/'; strcpy(path+i+1, fn);
- res = scan_files(path);
+ while (((res = f_readdir(&dirs, &statp->Finfo)) == FR_OK) &&
+ statp->Finfo.fname[0]) {
+ if (_FS_RPATH && statp->Finfo.fname[0] == '.')
+ continue;
+ fn = statp->Finfo.fname;
+ if (statp->Finfo.fattrib & AM_DIR) {
+ statp->AccDirs++;
+ path[i] = '/';
+ strcpy(path+i+1, fn);
+ res = scan_files(path, statp);
path[i] = '\0';
- if (res != FR_OK) break;
+ if (res != FR_OK)
+ break;
} else {
-// printf_P(PSTR("%s/%s\n"), path, fn);
- AccFiles++;
- AccSize += Finfo.fsize;
+ //printf_P(PSTR("%s/%s\n"), path, fn);
+ statp->AccFiles++;
+ statp->AccSize += statp->Finfo.fsize;
+ }
+ if (check_abort()) {
+ res = 255;
+ break;
}
}
}
@@ -99,64 +157,65 @@ FRESULT scan_files (
*/
command_ret_t do_fat_stat(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- FATFS FatFs, *fs;
- DWORD p1, p2;
+ FATFS *fs;
+ DWORD nfreeclst;
FRESULT res;
- char buffer[512];
+ char *path;
+ struct stat_dat_s statp;
(void) cmdtp; (void) flag; (void) argc;
- res = f_mount(&FatFs, argv[1], 0);
- if (!res)
- res = f_getfree(argv[1], &p2, &fs);
- if (res) {
- put_rc(res);
+ path = (char *) malloc(BUFFER_SIZE);
+ if (path == NULL) {
+ printf_P(PSTR("fatstat: Out of Memory!\n"));
+ free(path);
return CMD_RET_FAILURE;
}
- printf_P(PSTR(
- "FAT type: %u\n"
- "Bytes/Cluster: %lu\n"
- "Number of FATs: %u\n"
- "Root DIR entries: %u\n"
- "Sectors/FAT: %lu\n"
- "Number of clusters: %lu\n"
- "FAT start (lba): %lu\n"
- "DIR start (lba,cluster): %lu\n"
- "Data start (lba): %lu\n"),
- fs->fs_type, (DWORD)fs->csize * 512, fs->n_fats,
- fs->n_rootdir, fs->fsize, fs->n_fatent - 2,
- fs->fatbase, fs->dirbase, fs->database);
+ res = f_getfree(argv[1], &nfreeclst, &fs);
+ if (!res) {
+ printf_P(PSTR(
+ "FAT type: %u\n"
+ "Bytes/Cluster: %lu\n"
+ "Number of FATs: %u\n"
+ "Root DIR entries: %u\n"
+ "Sectors/FAT: %lu\n"
+ "Number of clusters: %lu\n"
+ "FAT start (lba): %lu\n"
+ "DIR start (lba,cluster): %lu\n"
+ "Data start (lba): %lu\n"),
+ fs->fs_type, (DWORD)fs->csize * 512, fs->n_fats,
+ fs->n_rootdir, fs->fsize, fs->n_fatent - 2,
+ fs->fatbase, fs->dirbase, fs->database);
#if _USE_LABEL
- TCHAR label[12];
- res = f_getlabel(argv[1], label, &p1);
- if (res) {
- put_rc(res);
- return CMD_RET_FAILURE;
- }
- printf_P(PSTR(
- "Volume name: %s\n"
- "Volume S/N: %04X-%04X\n"),
- label, (WORD)((DWORD)p1 >> 16), (WORD)(p1 & 0xFFFF));
+ TCHAR label[12];
+ DWORD serial;
+ res = f_getlabel(argv[1], label, &serial);
+ if (!res) {
+ printf_P(PSTR(
+ "Volume name: %s\n"
+ "Volume S/N: %04X-%04X\n"),
+ label, (WORD)(serial >> 16), (WORD)(serial & 0xFFFF));
+ }
#endif
- my_puts_P(PSTR("\n..."));
- AccSize = AccFiles = AccDirs = 0;
-
- strcpy(buffer, argv[1]);
+ if (!res) {
+ my_puts_P(PSTR("\nCounting... "));
+ statp.AccSize = statp.AccFiles = statp.AccDirs = 0;
+ strcpy(path, argv[1]);
- res = scan_files(buffer);
- if (res) {
- put_rc(res);
- return CMD_RET_FAILURE;
+ res = scan_files(path, &statp);
+ }
+ if (!res) {
+ printf_P(PSTR("\r%u files, %lu bytes.\n%u folders.\n"
+ "%lu KB total disk space.\n%lu KB available.\n"),
+ statp.AccFiles, statp.AccSize, statp.AccDirs,
+ (fs->n_fatent - 2) * (fs->csize / 2), nfreeclst * (fs->csize / 2)
+ );
+ }
}
- printf_P(PSTR("\r%u files, %lu bytes.\n%u folders.\n"
- "%lu KB total disk space.\n%lu KB available.\n"),
- AccFiles, AccSize, AccDirs,
- (fs->n_fatent - 2) * (fs->csize / 2), p2 * (fs->csize / 2)
- );
- res = f_mount(NULL, argv[1], 0);
+ free(path);
if (res) {
put_rc(res);
return CMD_RET_FAILURE;
@@ -171,7 +230,7 @@ command_ret_t do_fat_stat(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
*/
command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- FATFS FatFs, *fs;
+ FATFS *fs;
DIR Dir; /* Directory object */
FILINFO Finfo;
unsigned long p1;
@@ -185,9 +244,7 @@ command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
(void) cmdtp; (void) flag; (void) argc;
- res = f_mount(&FatFs, argv[1], 0);
- if (!res)
- res = f_opendir(&Dir, argv[1]);
+ res = f_opendir(&Dir, argv[1]);
if (res) {
put_rc(res);
return CMD_RET_FAILURE;
@@ -203,22 +260,21 @@ command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
} else {
s1++; p1 += Finfo.fsize;
}
- printf_P(PSTR("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %s"),
+ printf_P(PSTR("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu "),
(Finfo.fattrib & AM_DIR) ? 'D' : '-',
(Finfo.fattrib & AM_RDO) ? 'R' : '-',
(Finfo.fattrib & AM_HID) ? 'H' : '-',
(Finfo.fattrib & AM_SYS) ? 'S' : '-',
(Finfo.fattrib & AM_ARC) ? 'A' : '-',
(Finfo.fdate >> 9) + 1980, (Finfo.fdate >> 5) & 15, Finfo.fdate & 31,
- (Finfo.ftime >> 11), (Finfo.ftime >> 5) & 63,
- Finfo.fsize, &(Finfo.fname[0]));
+ (Finfo.ftime >> 11), (Finfo.ftime >> 5) & 63, Finfo.fsize);
#if _USE_LFN
- for (int i = strlen(Finfo.fname); i < 14; i++)
- putchar(' ');
- printf_P(PSTR("%s\n"), Lfname);
+ printf_P(PSTR("%s\n"), *Lfname ? Lfname : Finfo.fname);
#else
- putchar('\n');
+ printf_P(PSTR("%s\n"), Finfo.fname);
#endif
+ if (check_abort())
+ break;
}
if (res == FR_OK) {
@@ -235,146 +291,153 @@ command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
return CMD_RET_SUCCESS;
}
+static
+FRESULT mkpath(TCHAR *path)
+{
+ /* TODO: */
+ (void) path;
+#if 0
+ FILINFO fd
+ TCHAR *p, *q;
+ FRESULT ret;
+
+#if _USE_LFN
+ fd.lfname = 0;
+#endif
+
+
+ res = f_stat (path, &fd)
+
+ p = strchr(path, ':');
+ if (p == NULL || *++p == '\0' || *p++ != '/')
+ return FR_OK;
+
+ while ((q = strchr(p, '/')) != NULL) {
+ *q = '\0';
+ ret = f_mkdir(path);
+ *q = '/';
+ if (ret != FR_OK && ret != FR_EXIST)
+ return ret;
+ p = q + 1;
+ }
+#endif
+
+ return FR_OK;
+}
/*
- * fatread - load binary file from a dos filesystem
- * <d:/path/filename> <addr> [bytes [pos]]
+ * fatread/write - load binary file to/from a dos filesystem
+ * read <d:/path/filename> <addr> [bytes [pos]]
+ * write <d:/path/filename> <addr> <bytes>
*/
-command_ret_t do_fat_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_fat_rw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- FATFS FatFs;
FIL File;
- unsigned long bytes = 0x80000;
- unsigned long pos= 0;
- unsigned long bytes_read;
uint32_t addr;
+ unsigned long bytes;
+ unsigned long pos;
+ unsigned long bytes_rw;
+
+ bool dowrite = (argv[0][3] == 'w');
FRESULT res;
bool buserr = 0;
uint32_t timer;
- uint8_t buffer[512];
+ uint8_t *buffer;
(void) cmdtp; (void) flag;
- if (argc < 3)
+ if (argc < (dowrite ? 4 : 3))
return CMD_RET_USAGE;
addr = strtoul(argv[2], 0, 16);
+ if (addr >= MAX_MEMORY) {
+ printf_P(PSTR("address too high: 0x%0lx\n"), addr);
+ return CMD_RET_FAILURE;
+ }
if (argc > 3)
bytes = strtoul(argv[3], 0, 16);
+ else
+ bytes = MAX_MEMORY;
if (argc > 4)
pos = strtoul(argv[4], 0, 16);
+ else
+ pos = 0;
+
+ if (addr + bytes > MAX_MEMORY)
+ bytes = MAX_MEMORY - addr;
- res = f_mount(&FatFs, argv[1], 0);
+ buffer = (uint8_t *) malloc(BUFFER_SIZE);
+ if (buffer == NULL) {
+ printf_P(PSTR("fatstat: Out of Memory!\n"));
+ free(buffer);
+ return CMD_RET_FAILURE;
+ }
+
+ if (dowrite) {
+ res = mkpath(argv[1]);
+ }
if (!res) {
- res = f_open(&File, argv[1], FA_READ);
+ res = f_open(&File, argv[1], dowrite ? FA_WRITE | FA_CREATE_ALWAYS
+ : FA_READ );
if (!res) {
res = f_lseek(&File, pos);
if (!res) {
- bytes_read = 0;
+ bytes_rw = 0;
timer = get_timer(0);
while (bytes) {
unsigned int cnt, br;
- if (bytes >= sizeof buffer) {
- cnt = sizeof buffer;
- bytes -= sizeof buffer;
+ if (bytes >= BUFFER_SIZE) {
+ cnt = BUFFER_SIZE;
+ bytes -= BUFFER_SIZE;
} else {
cnt = bytes; bytes = 0;
}
- res = f_read(&File, buffer, cnt, &br);
- if (res != FR_OK)
- break;
- if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
- buserr = 1;
- break;
+ if (dowrite) {
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ buserr = 1;
+ break;
+ }
+ z80_read_block(buffer, addr, cnt);
+ z80_bus_cmd(Release);
+ res = f_write(&File, buffer, cnt, &br);
+ if (res != FR_OK)
+ break;
+ } else {
+ res = f_read(&File, buffer, cnt, &br);
+ if (res != FR_OK)
+ break;
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ buserr = 1;
+ break;
+ }
+ z80_write_block(buffer, addr, br);
+ z80_bus_cmd(Release);
}
- z80_write_block(buffer, addr, br);
- z80_bus_cmd(Release);
addr += br;
- bytes_read += br;
- if (cnt != br)
+ bytes_rw += br;
+ if (cnt != br) {
+ if (dowrite)
+ printf_P(PSTR("Disk full?\n"));
+ break;
+ }
+ if (check_abort())
break;
}
+
+ FRESULT fr = f_close(&File);
+ if (!res)
+ res = fr;
timer = get_timer(timer);
- printf_P(PSTR("%lu bytes read with %lu bytes/sec.\n"),
- bytes_read, timer ? (bytes_read * 1000 / timer) : 0);
+ printf_P(PSTR("%lu (0x%lx) bytes read/written with %lu bytes/sec.\n"),
+ bytes_rw, bytes_rw, timer ? (bytes_rw * 1000 / timer) : 0);
}
}
- f_mount(NULL, argv[1], 0);
}
- if (buserr)
- my_puts_P(PSTR("Bus timeout\n"));
- if (res)
- put_rc(res);
- if (buserr || res)
- return CMD_RET_FAILURE;
-
- return CMD_RET_SUCCESS;
-}
-
-/*
- * fatwrite - write file into a dos filesystem
- * <d:/path/filename> <addr> <bytes>
- */
-command_ret_t do_fat_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- FATFS FatFs;
- FIL File;
- unsigned long bytes;
- unsigned long bytes_written;
- uint32_t addr;
- FRESULT res;
- bool buserr = 0;
- uint32_t timer;
- uint8_t buffer[512];
-
- (void) cmdtp; (void) flag;
-
- if (argc < 4)
- return CMD_RET_USAGE;
-
- addr = strtoul(argv[2], 0, 16);
- bytes = strtoul(argv[3], 0, 16);
-
- res = f_mount(&FatFs, argv[1], 0);
- if (!res) {
- res = f_open(&File, argv[1], FA_CREATE_ALWAYS | FA_WRITE);
- if (!res) {
- bytes_written = 0;
- timer = get_timer(0);
- while (bytes) {
- unsigned int cnt, br;
-
- if (bytes >= sizeof buffer) {
- cnt = sizeof buffer;
- bytes -= sizeof buffer;
- } else {
- cnt = bytes; bytes = 0;
- }
- if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
- buserr = 1;
- break;
- }
- z80_read_block(buffer, addr, cnt);
- z80_bus_cmd(Release);
- res = f_write(&File, buffer, cnt, &br);
- if (res != FR_OK)
- break;
- addr += br;
- bytes_written += br;
- if (cnt != br)
- break;
- }
- res = f_close(&File);
- timer = get_timer(timer);
- printf_P(PSTR("%lu bytes written with %lu bytes/sec.\n"),
- bytes_written, timer ? (bytes_written * 1000 / timer) : 0);
- }
- f_mount(NULL, argv[1], 0);
- }
+ free(buffer);
if (buserr)
my_puts_P(PSTR("Bus timeout\n"));
diff --git a/avr/cmd_gpio.c b/avr/cmd_gpio.c
index 84723d2..5589381 100644
--- a/avr/cmd_gpio.c
+++ b/avr/cmd_gpio.c
@@ -1,3 +1,9 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
#include "common.h"
#include <stdlib.h>
#include <string.h>
@@ -29,6 +35,8 @@ static void pinnames_get(void)
memset(pin_names, 0, sizeof(pin_names));
pin_names_width = 0;
+/* TODO: enters endless loop on wrong parameters */
+
if ((lp = getenv(PSTR(ENV_PINALIAS))) != NULL) {
pin_names[namestr] = strdup(lp);
ptr = strtok_P(pin_names[namestr], delim1);
diff --git a/avr/cmd_help.c b/avr/cmd_help.c
index 8f81b2d..010339d 100644
--- a/avr/cmd_help.c
+++ b/avr/cmd_help.c
@@ -1,3 +1,11 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
#include "common.h"
#include "command.h"
diff --git a/avr/cmd_loadcpm3.c b/avr/cmd_loadcpm3.c
new file mode 100644
index 0000000..da1be37
--- /dev/null
+++ b/avr/cmd_loadcpm3.c
@@ -0,0 +1,172 @@
+/*
+ * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "common.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "command.h"
+#include "env.h"
+#include "ff.h"
+#include "con-utils.h"
+#include "z80-if.h"
+#include "debug.h"
+
+
+#define RS 128 /* CP/M record size */
+
+/*
+ * Load Routine
+ *
+ * Input: addr = Page Address of load top
+ * len = Length in pages of module to read
+ *
+ */
+int load(FIL *File, uint32_t addr, uint8_t len)
+{
+ uint8_t buffer[RS];
+ unsigned int br; /* bytes read */
+ int res;
+
+ len *= 2; /* length in records of module */
+ //debug("## load: addr: 0x%.4X, records: 0x%.4X, (%u)\n", addr, len, len);
+
+ for (; len; len--) {
+ addr -= RS;
+ res = f_read(File, buffer, RS, &br);
+ if (res || br != RS) {
+ return 1;
+ }
+
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ my_puts_P(PSTR("Bus timeout\n"));
+ return 2;
+ }
+ z80_write_block(buffer, addr, RS);
+ z80_bus_cmd(Release);
+ //debug("## written: 0x%.4X\n", addr);
+ }
+
+ return 0;
+}
+
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+
+command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ uint16_t mem_top;
+ uint8_t res_len;
+ uint16_t bank_top;
+ uint8_t bank_len;
+ uint16_t osentry_addr = 0;
+ uint32_t common_base, banked_base;
+ char *fname;
+ FIL File;
+ /* TODO: put CONFIG_CPM3_SYSFILE in flash */
+ char default_fname[] = CONFIG_CPM3_SYSFILE;
+ unsigned int br; /* bytes read */
+ uint8_t buffer[RS];
+ int res;
+
+ (void) cmdtp; (void) flag;
+
+
+ common_base = getenv_ulong(PSTR(ENV_CPM3_COMMON_BASE), 16,
+ CONFIG_CPM3_COMMON_BASE);
+ banked_base = getenv_ulong(PSTR(ENV_CPM3_BANKED_BASE), 16,
+ CONFIG_CPM3_BANKED_BASE);
+
+ if (argc > 3)
+ banked_base = strtoul(argv[3], NULL, 16);
+ if (argc > 2)
+ banked_base = strtoul(argv[2], NULL, 16);
+
+ fname = getenv(PSTR(ENV_CPM3_SYSFILE));
+ if (argc > 2) {
+ fname = argv[2];
+ }
+ if (fname == NULL || *fname == '\0')
+ fname = default_fname;
+
+ res = f_open(&File, fname, FA_READ );
+ if (res) {
+ printf_P(PSTR("Error: failed to open '%s'\n"), fname);
+ return CMD_RET_FAILURE;
+ }
+
+ printf_P(PSTR("Loading: '%s'...\n"), fname);
+
+ /* read the load record */
+ res = f_read(&File, buffer, RS, &br);
+ if (res || br != RS)
+ goto out;
+
+ mem_top = buffer[0] << 8;
+ res_len = buffer[1];
+ bank_top = buffer[2] << 8;
+ bank_len = buffer[3];
+ osentry_addr = buffer[4] + (buffer[5] << 8);
+
+ /* read display info */
+ res = f_read(&File, buffer, RS, &br);
+ if (res || br != RS)
+ goto out;
+
+ /* print the info */
+ buffer[RS-1] = '$';
+ uint8_t *p = memchr(buffer, '$', RS);
+ *p = '\0';
+ my_puts((char *)buffer);
+
+ /* Main System Load */
+
+ /* Load Common Portion of System */
+ if ((res = load(&File, common_base + mem_top, res_len)) != 0)
+ goto out;
+
+ /* Load Banked Portion of System */
+ res = load(&File, banked_base + bank_top, bank_len);
+
+out:
+ f_close(&File);
+
+ if (res) {
+ printf_P(PSTR("Error: failed to read '%s'\n"), fname);
+ return CMD_RET_FAILURE;
+ } else {
+ if (res_len != 0) {
+ if (osentry_addr + common_base > 0xffff) {
+ z80_bus_cmd(Request);
+ if (z80_read(osentry_addr + common_base) == 0xc3) {
+ osentry_addr = z80_read(osentry_addr+common_base+1) +
+ (z80_read(osentry_addr + common_base+2) << 8);
+ }
+ z80_bus_cmd(Release);
+ if (banked_base + osentry_addr > 0xffff)
+ osentry_addr = 0;
+ }
+ setenv_hex(PSTR(ENV_STARTADDRESS), osentry_addr);
+ }
+ printf_P(PSTR("Loaded: Resident: "));
+ if (res_len != 0)
+ printf_P(PSTR("0x%.5lX-0x%.5lX, "),
+ (common_base + mem_top) - res_len*256,
+ (common_base + mem_top) - 1);
+ else
+ printf_P(PSTR(" - "));
+ printf_P(PSTR("Banked: "));
+ if (bank_len != 0)
+ printf_P(PSTR("0x%.5lX-0x%.5lX\n"),
+ (banked_base + bank_top) - bank_len*256,
+ (banked_base + bank_top) - 1);
+ else
+ printf_P(PSTR(" - \n"));
+
+ return CMD_RET_SUCCESS;
+ }
+}
diff --git a/avr/cmd_loadihex.c b/avr/cmd_loadihex.c
new file mode 100644
index 0000000..18d5331
--- /dev/null
+++ b/avr/cmd_loadihex.c
@@ -0,0 +1,261 @@
+/*
+ * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "common.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdbool.h>
+
+#include "command.h"
+#include "con-utils.h"
+#include "z80-if.h"
+#include "debug.h"
+
+
+uint32_t detect_ramsize(void)
+{
+ uint32_t addr;
+ uint8_t save_addr, save_0;
+ const uint8_t PATTERN_1 = 0x55;
+ const uint8_t PATTERN_2 = ~PATTERN_1;
+
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ my_puts_P(PSTR("Bus timeout\n"));
+ return 0;
+ }
+
+ save_0 = z80_read(0);
+ z80_write(0, PATTERN_1);
+
+ for (addr=1; addr < CONFIG_SYS_RAMSIZE_MAX; addr <<= 1) {
+ save_addr = z80_read(addr);
+ z80_write(addr, PATTERN_2);
+ if (z80_read(0) != PATTERN_1 || z80_read(addr) != PATTERN_2)
+ break;
+ z80_write(addr, save_addr);
+ }
+ z80_write(0, save_0);
+ z80_bus_cmd(Release);
+
+ return addr;
+}
+
+typedef enum {
+ IHX_OK,
+ IHX_BROKEN,
+ IHX_CHKSUMERR
+} ihx_rstat_t;
+
+typedef struct {
+ ihx_rstat_t status;
+ int8_t type;
+ uint8_t len;
+ uint16_t address;
+ uint8_t data[256];
+} ihex_t;
+
+
+static
+int get_hexdigit(void) {
+
+ int c;
+ c = toupper(my_getchar(1));
+ if (isxdigit(c)) {
+ c -= '0';
+ if (c > 9)
+ c -= ('A' - '0' - 10);
+ return c;
+ } else
+ return -1;
+}
+
+static
+int get_hexbyte(void) {
+
+ uint8_t i,j;
+
+ if ((i = (uint8_t) get_hexdigit()) < 0x10)
+ if ((j = (uint8_t) get_hexdigit()) < 0x10) {
+ return (i<<4) + j;
+ }
+
+ return -1;
+}
+
+
+static
+int ihex_get_record(ihex_t *rec) {
+
+ int c;
+ uint8_t sum;
+
+ rec->status = IHX_BROKEN;
+ rec->len = 0;
+ rec->type = 0xff;
+
+ while ((c = my_getchar(0)) != ':') {
+ if (c == 0x03)
+ return -1; /* Control-C */
+ if (c == 0x04) {
+ rec->status = IHX_OK;
+ return 0; /*Control-D, EOF */
+ }
+ }
+
+ if ((c = get_hexbyte()) < 0) /* Start code */
+ return -1;
+ sum = c;
+ rec->len = c;
+ if ((c = get_hexbyte()) < 0) /* Byte Count */
+ return -1;
+ sum += c;
+ rec->address = c * 256;
+ if ((c = get_hexbyte()) < 0) /* Address */
+ return -1;
+ sum += c;
+ rec->address += c;
+ if ((c = get_hexbyte()) < 0) /* Record type */
+ return -1;
+ sum += c;
+ rec->type = c;
+
+ if (rec->len) { /* Record Data */
+ uint8_t n;
+
+ for (n = 0; n < rec->len; n++) {
+ if ((c = get_hexbyte()) < 0)
+ break;
+ sum += c;
+ rec->data[n] = c;
+ }
+
+ if (n < rec->len) {
+ return -1;
+ }
+ }
+
+ c = get_hexbyte(); /* Check sum */
+
+ if (c >= 0) {
+ sum += c;
+ if (sum == 0)
+ rec->status = IHX_OK;
+ else
+ rec->status = IHX_CHKSUMERR;
+ }
+
+ return rec->len;
+}
+
+
+command_ret_t do_loadihex(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ long offset = 0;
+ uint32_t base_address = 0;
+ uint32_t address_max = detect_ramsize();
+ uint32_t address_high = 0;
+ uint32_t address_low = address_max;
+ command_ret_t rcode = CMD_RET_FAILURE;
+ ihex_t rec;
+ bool firstrec = true;
+
+ (void) cmdtp; (void) flag;
+
+
+ if (argc > 1)
+ offset = strtol(argv[1], NULL, 16);
+
+ printf_P(PSTR("Waiting for Intel Hex Records...\n"));
+
+ while (ihex_get_record(&rec) > 0 &&
+ rec.status == IHX_OK &&
+ rec.type != 1 ) {
+
+ switch (rec.type) {
+ case 0: /* Data record */
+ if (firstrec) {
+ printf_P(PSTR("Loading: 0x....."));
+ firstrec = false;
+ }
+ if (rec.len) {
+ uint32_t addr = base_address + rec.address + offset;
+ if (addr < address_low)
+ address_low = addr;
+ if (addr+rec.len > address_high)
+ address_high = addr + rec.len;
+
+// debug("low: 0x%.5lX, high: 0x%.5lX, max: 0x%.5lX, addr: 0x%.5lX, len: %d\n",
+// address_low, address_high, address_max, addr, rec.len);
+ printf_P(PSTR("\b\b\b\b\b%.5lX"), addr);
+ if (addr < address_max) {
+ uint32_t tmplen = address_max - addr;
+ if (rec.len > tmplen)
+ rec.len = tmplen;
+
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ my_puts_P(PSTR("Bus timeout\n"));
+ return CMD_RET_FAILURE;
+ }
+ z80_write_block(rec.data, /* src */
+ addr, /* dest */
+ rec.len); /* len */
+ z80_bus_cmd(Release);
+ }
+ }
+ break;
+
+#if 0
+ case 1: /* EOF record */
+ break;
+#endif
+ case 2: /* Extended Segment Address Record */
+ base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 4;
+ break;
+
+ case 4: /* Extended Linear Address Record */
+ base_address = (uint32_t)((rec.data[0] << 8) + rec.data[1]) << 16;
+ break;
+
+ case 3: /* Start Segment Address Record (ignored)*/
+ case 5: /* Start Linear Address Record (ignored)*/
+ break;
+
+ }
+ }
+
+ switch (rec.status) {
+ case IHX_OK:
+ rcode = CMD_RET_SUCCESS;
+ break;
+
+ case IHX_BROKEN:
+ case IHX_CHKSUMERR:
+ printf_P(PSTR("Broken Hex Record or loading interrupted!\n"));
+ break;
+ }
+
+
+ for (uint_fast8_t i=0; i<100; ++i) {
+ /* flush input buffer */
+ while (my_getchar(0) > 0)
+ ;
+ udelay(1000);
+ }
+
+
+ printf_P(PSTR("\nData loaded: "));
+ if (address_low >= MIN(address_high, address_max))
+ printf_P(PSTR("None.\n"));
+ else
+ printf_P(PSTR("low: 0x%.5lX high: 0x%.5lX\n"), address_low,
+ MIN(address_high, address_max) - 1);
+
+ if (address_high > address_max)
+ printf_P(PSTR("Data above highest RAM address "
+ "(in range 0x%.5lX - 0x%.5lX) ignored!\n"), address_max, address_high - 1);
+
+ return rcode;
+}
diff --git a/avr/cmd_mem.c b/avr/cmd_mem.c
index 0bc5742..101b912 100644
--- a/avr/cmd_mem.c
+++ b/avr/cmd_mem.c
@@ -1,4 +1,6 @@
/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
@@ -14,13 +16,15 @@
#include "common.h"
#include <stdlib.h>
#include <ctype.h>
+#include <avr/interrupt.h>
#include "command.h"
#include "cli_readline.h"
#include "print-utils.h"
#include "con-utils.h"
+#include "timer.h"
#include "z80-if.h"
-//#include "debug.h"
+#include "debug.h"
#ifndef CONFIG_SYS_MEMTEST_SCRATCH
@@ -148,8 +152,8 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
if (incrflag)
addr += nbytes ? -1 : 1;
nbytes = 1;
- }
- else {
+
+ } else {
char *endp;
data = strtoul(console_buffer, &endp, 16);
nbytes = endp - console_buffer;
@@ -220,55 +224,35 @@ command_ret_t do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
#ifdef CONFIG_MX_CYCLIC
command_ret_t do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- int i;
uint32_t count;
+ uint32_t ts;
+
+ (void) cmdtp;
+ (void) flag;
if (argc < 4)
return CMD_RET_USAGE;
count = strtoul(argv[3], NULL, 10);
+ clear_ctrlc(); /* forget any previous Control C */
for (;;) {
- do_mem_md (NULL, 0, 3, argv);
-
- /* delay for <count> ms... */
-/* TODO: use timer */
- for (i=0; i<count; i++)
- udelay (1000);
-
- /* check for ctrl-c to abort... */
- if (ctrlc()) {
- my_puts_P(PSTR("Abort\n"));
- return CMD_RET_SUCCESS;
- }
- }
-
- return CMD_RET_SUCCESS;
-}
-
-command_ret_t do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- int i;
- uint32_t count;
- if (argc < 4)
- return CMD_RET_USAGE;
-
- count = strtoul(argv[3], NULL, 10);
+ if (argv[0][1] == 'd')
+ do_mem_md (NULL, 0, 3, argv);
+ else
+ do_mem_mw (NULL, 0, 3, argv);
- for (;;) {
- do_mem_mw (NULL, 0, 3, argv);
/* delay for <count> ms... */
-/* TODO: use timer */
- for (i=0; i<count; i++)
- udelay (1000);
-
- /* check for ctrl-c to abort... */
- if (ctrlc()) {
- my_puts_P(PSTR("Abort\n"));
- return CMD_RET_SUCCESS;
- }
+ ts = get_timer(0);
+ do {
+ /* check for ctrl-c to abort... */
+ if (had_ctrlc() || ctrlc()) {
+ my_puts_P(PSTR("Abort\n"));
+ return CMD_RET_SUCCESS;
+ }
+ } while (get_timer(ts) < count);
}
return CMD_RET_SUCCESS;
@@ -415,27 +399,26 @@ command_ret_t do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
my_puts_P(PSTR("Bus timeout\n"));
return CMD_RET_FAILURE;
}
+ cli();
for (;;)
z80_read(addr);
- z80_bus_cmd(Release);
}
if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
my_puts_P(PSTR("Bus timeout\n"));
return CMD_RET_FAILURE;
}
+ cli();
for (;;) {
uint32_t i = length;
uint32_t p = addr;
while (i-- > 0)
z80_read(p++);
}
- z80_bus_cmd(Release);
return CMD_RET_SUCCESS;
}
-#ifdef CONFIG_LOOPW
command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
uint32_t addr, length;
@@ -455,7 +438,8 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a
data = strtoul(argv[3], NULL, 16);
- /* We want to optimize the loops to run as fast as possible.
+ /*
+ * We want to optimize the loops to run as fast as possible.
* If we have only one object, just run infinite loops.
*/
if (length == 1) {
@@ -463,6 +447,7 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a
my_puts_P(PSTR("Bus timeout\n"));
return CMD_RET_FAILURE;
}
+ cli();
for (;;)
z80_write(addr, data);
}
@@ -471,6 +456,7 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a
my_puts_P(PSTR("Bus timeout\n"));
return CMD_RET_FAILURE;
}
+ cli();
for (;;) {
uint32_t i = length;
uint32_t p = addr;
@@ -478,35 +464,33 @@ command_ret_t do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const a
z80_write(p++, data);
}
}
-#endif /* CONFIG_LOOPW */
+
+//#define CONFIG_SYS_ALT_MEMTEST
#ifdef CONFIG_CMD_MEMTEST
-static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_addr,
- vu_long *dummy)
+static uint32_t mem_test_alt(uint32_t start_addr, uint32_t end_addr)
{
- vu_long *addr;
+ uint32_t addr;
+ uint32_t dummy;
uint32_t errs = 0;
- uint32_t val, readback;
- int j;
- vu_long offset;
- vu_long test_offset;
- vu_long pattern;
- vu_long temp;
- vu_long anti_pattern;
- vu_long num_words;
- static const FLASH uint32_t bitpattern[] = {
- 0x00000001, /* single bit */
- 0x00000003, /* two adjacent bits */
- 0x00000007, /* three adjacent bits */
- 0x0000000F, /* four adjacent bits */
- 0x00000005, /* two non-adjacent bits */
- 0x00000015, /* three non-adjacent bits */
- 0x00000055, /* four non-adjacent bits */
- 0xaaaaaaaa, /* alternating 1/0 */
+ uint32_t offset;
+ uint32_t test_offset;
+ uint8_t pattern;
+ uint8_t anti_pattern;
+ uint8_t temp;
+ uint32_t num_bytes;
+
+ static const FLASH uint8_t bitpattern[] = {
+ 0x01, /* single bit */
+ 0x03, /* two adjacent bits */
+ 0x07, /* three adjacent bits */
+ 0x0F, /* four adjacent bits */
+ 0x05, /* two non-adjacent bits */
+ 0x15, /* three non-adjacent bits */
+ 0x55, /* four non-adjacent bits */
+ 0xaa, /* alternating 1/0 */
};
- num_words = (end_addr - start_addr) / sizeof(vu_long);
-
/*
* Data line test: write a pattern to the first
* location, write the 1's complement to a 'parking'
@@ -524,35 +508,39 @@ static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_add
* '0's and '0' bits through a field of '1's (i.e.
* pattern and ~pattern).
*/
- addr = buf;
- for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) {
- val = bitpattern[j];
- for (; val != 0; val <<= 1) {
- *addr = val;
- *dummy = ~val; /* clear the test data off the bus */
- readback = *addr;
- if (readback != val) {
+ addr = start_addr;
+ dummy = start_addr+1;
+ for (unsigned int j = 0; j < ARRAY_SIZE(bitpattern); j++) {
+ pattern = bitpattern[j];
+ for (; pattern != 0; pattern <<= 1) {
+ anti_pattern = ~pattern;
+ z80_write(addr, pattern);
+ z80_write(dummy, anti_pattern); /* clear the test data off the bus */
+ temp = z80_read(addr);
+ if (temp != pattern) {
printf_P(PSTR("FAILURE (data line): "
- "expected %05lx, actual %05lx\n"),
- val, readback);
+ "expected %02x, actual %02x\n"),
+ pattern, temp);
errs++;
- if (ctrlc())
- return -1;
}
- *addr = ~val;
- *dummy = val;
- readback = *addr;
- if (readback != ~val) {
+ z80_write(addr, anti_pattern);
+ z80_write(dummy, pattern); /* clear the test data off the bus */
+ temp = z80_read(addr);
+ if (temp != anti_pattern) {
printf_P(PSTR("FAILURE (data line): "
- "Is %05lx, should be %05lx\n"),
- readback, ~val);
+ "Is %02x, should be %02x\n"),
+ temp, anti_pattern);
errs++;
- if (ctrlc())
- return -1;
}
}
+
+ if (ctrlc())
+ return -1;
}
+ if (errs)
+ return errs;
+
/*
* Based on code whose Original Author and Copyright
* information follows: Copyright (c) 1998 by Michael
@@ -587,59 +575,61 @@ static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_add
*
* Returns: 0 if the test succeeds, 1 if the test fails.
*/
- pattern = (vu_long) 0xaaaaaaaa;
- anti_pattern = (vu_long) 0x55555555;
- debug("%s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_words);
+ num_bytes = (end_addr - start_addr) / sizeof(uint8_t);
+
+ pattern = 0xaa;
+ anti_pattern = 0x55;
+
+// debug("## %s:%d: length = 0x%.5lx\n", __func__, __LINE__, num_bytes);
/*
* Write the default pattern at each of the
* power-of-two offsets.
*/
- for (offset = 1; offset < num_words; offset <<= 1)
- addr[offset] = pattern;
+ for (offset = 1; offset < num_bytes; offset <<= 1)
+ z80_write(addr+offset, pattern);
/*
* Check for address bits stuck high.
*/
- test_offset = 0;
- addr[test_offset] = anti_pattern;
+ z80_write(start_addr, anti_pattern);
- for (offset = 1; offset < num_words; offset <<= 1) {
- temp = addr[offset];
+ for (offset = 1; offset < num_bytes; offset <<= 1) {
+ temp = z80_read(start_addr + offset);
if (temp != pattern) {
- printf_P(PSTR("\nFAILURE: Address bit stuck high @ 0x%.5lx:"
- " expected 0x%.5lx, actual 0x%.5lx\n"),
- start_addr + offset*sizeof(vu_long),
- pattern, temp);
+ printf_P(PSTR("FAILURE: Address bit stuck high @ 0x%.5lx:"
+ " expected 0x%.2x, actual 0x%.2x\n"),
+ start_addr + offset, pattern, temp);
errs++;
if (ctrlc())
return -1;
}
}
- addr[test_offset] = pattern;
+ z80_write(start_addr, pattern);
/*
* Check for addr bits stuck low or shorted.
*/
- for (test_offset = 1; test_offset < num_words; test_offset <<= 1) {
- addr[test_offset] = anti_pattern;
+ for (test_offset = 1; test_offset < num_bytes; test_offset <<= 1) {
+ z80_write(start_addr + test_offset, anti_pattern);
- for (offset = 1; offset < num_words; offset <<= 1) {
- temp = addr[offset];
+ for (offset = 1; offset < num_bytes; offset <<= 1) {
+ temp = z80_read(start_addr + offset);
if ((temp != pattern) && (offset != test_offset)) {
- printf_P(PSTR("\nFAILURE: Address bit stuck low or"
- " shorted @ 0x%.5lx: expected 0x%.5lx,"
- " actual 0x%.5lx\n"),
- start_addr + offset*sizeof(vu_long),
- pattern, temp);
+ printf_P(PSTR("FAILURE: Address bit stuck low or shorted"
+ " @ 0x%.5lx: expected 0x%.2x, actual 0x%.2x\n"),
+ start_addr + offset, pattern, temp);
errs++;
if (ctrlc())
return -1;
}
}
- addr[test_offset] = pattern;
+ z80_write(start_addr + test_offset, pattern);
}
+ if (errs)
+ return errs;
+
/*
* Description: Test the integrity of a physical
* memory device by performing an
@@ -652,111 +642,50 @@ static uint32_t mem_test_alt(vu_long *buf, uint32_t start_addr, uint32_t end_add
*
* Returns: 0 if the test succeeds, 1 if the test fails.
*/
- num_words++;
+ num_bytes++;
/*
* Fill memory with a known pattern.
*/
- for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
- addr[offset] = pattern;
- }
+ for (pattern = 1, addr = start_addr; addr <= end_addr; pattern++, addr++)
+ z80_write(addr, pattern);
/*
* Check each location and invert it for the second pass.
*/
- for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
- temp = addr[offset];
+ for (pattern = 1, addr = start_addr; addr <= end_addr; pattern++, addr++) {
+ temp = z80_read(addr);
if (temp != pattern) {
- printf_P(PSTR("\nFAILURE (read/write) @ 0x%.5lx:"
- " expected 0x%.5lx, actual 0x%.5lx)\n"),
- start_addr + offset*sizeof(vu_long),
- pattern, temp);
+ printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:"
+ " expected 0x%.2x, actual 0x%.2x)\n"),
+ addr, pattern, temp);
errs++;
if (ctrlc())
return -1;
}
anti_pattern = ~pattern;
- addr[offset] = anti_pattern;
+ z80_write(addr, anti_pattern);
}
/*
* Check each location for the inverted pattern and zero it.
*/
- for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
- WATCHDOG_RESET();
+ for (pattern = 1, addr = start_addr; addr <= end_addr; pattern++, addr++) {
anti_pattern = ~pattern;
- temp = addr[offset];
+ temp = z80_read(addr);
if (temp != anti_pattern) {
- printf_P(PSTR("\nFAILURE (read/write): @ 0x%.5lx:"
- " expected 0x%.5lx, actual 0x%.5lx)\n"),
- start_addr + offset*sizeof(vu_long),
- anti_pattern, temp);
+ printf_P(PSTR("FAILURE (read/write) @ 0x%.5lx:"
+ " expected 0x%.2x, actual 0x%.2x)\n"),
+ start_addr, anti_pattern, temp);
errs++;
if (ctrlc())
return -1;
}
- addr[offset] = 0;
+ z80_write(addr, 0);
}
- return 0;
-}
-
-static uint32_t mem_test_quick(vu_long *buf, uint32_t start_addr, uint32_t end_addr,
- vu_long pattern, int iteration)
-{
- vu_long *end;
- vu_long *addr;
- uint32_t errs = 0;
- uint32_t incr, length;
- uint32_t val, readback;
-
- /* Alternate the pattern */
- incr = 1;
- if (iteration & 1) {
- incr = -incr;
- /*
- * Flip the pattern each time to make lots of zeros and
- * then, the next time, lots of ones. We decrement
- * the "negative" patterns and increment the "positive"
- * patterns to preserve this feature.
- */
- if (pattern & 0x80000000)
- pattern = -pattern; /* complement & increment */
- else
- pattern = ~pattern;
- }
- length = (end_addr - start_addr) / sizeof(uint32_t);
- end = buf + length;
- printf_P(PSTR("\rPattern %08lX Writing..."
- "%12s"
- "\b\b\b\b\b\b\b\b\b\b"),
- pattern, "");
-
- for (addr = buf, val = pattern; addr < end; addr++) {
- *addr = val;
- val += incr;
- }
-
- my_puts_P(PSTR("Reading..."));
-
- for (addr = buf, val = pattern; addr < end; addr++) {
- readback = *addr;
- if (readback != val) {
- uint32_t offset = addr - buf;
-
- printf_P(PSTR("\nMem error @ 0x%08X: "
- "found %08lX, expected %08lX\n"),
- (unsigned int)(uintptr_t)(start_addr + offset*sizeof(vu_long)),
- readback, val);
- errs++;
- if (ctrlc())
- return -1;
- }
- val += incr;
- }
-
- return 0;
+ return errs;
}
/*
@@ -767,77 +696,61 @@ static uint32_t mem_test_quick(vu_long *buf, uint32_t start_addr, uint32_t end_a
command_ret_t do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
- uint32_t start, end;
- vu_long *buf, *dummy;
- int iteration_limit;
-/* TODO: command_ret_t */
+ uint32_t start = 0;
+ uint32_t end;
+ unsigned int iteration_limit = 0;
+ unsigned int iteration;
+ uint32_t errs = 0; /* number of errors */
int ret;
- uint32_t errs = 0; /* number of errors, or -1 if interrupted */
- uint32_t pattern;
- int iteration;
-#if defined(CONFIG_SYS_ALT_MEMTEST)
- const int alt_test = 1;
-#else
- const int alt_test = 0;
-#endif
+
+ (void) cmdtp;
+ (void) flag;
if (argc > 1)
start = strtoul(argv[1], NULL, 16);
- else
- start = CONFIG_SYS_MEMTEST_START;
if (argc > 2)
end = strtoul(argv[2], NULL, 16);
else
- end = CONFIG_SYS_MEMTEST_END;
+ end = CONFIG_SYS_RAMSIZE_MAX - 1;
if (argc > 3)
- pattern = (uint32_t)strtoul(argv[3], NULL, 16);
- else
- pattern = 0;
+ iteration_limit = (unsigned int) strtoul(argv[3], NULL, 16);
- if (argc > 4)
- iteration_limit = (uint32_t)strtoul(argv[4], NULL, 16);
- else
- iteration_limit = 0;
+ printf_P(PSTR("Testing %05lx ... %05lx:\n"), start, end);
+// debug("## %s:%d: start %#05lx end %#05lx\n", __func__, __LINE__, start, end);
- printf_P(PSTR("Testing %08x ... %08x:\n"), (unsigned int)start, (unsigned int)end);
- debug("%s:%d: start %#05lx end %#05lx\n", __func__, __LINE__,
- start, end);
+ clear_ctrlc(); /* forget any previous Control C */
-/* TODO: */
-// buf = map_sysmem(start, end - start);
-// dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long));
for (iteration = 0;
!iteration_limit || iteration < iteration_limit;
iteration++) {
- if (ctrlc()) {
- errs = -1UL;
- break;
- }
printf_P(PSTR("Iteration: %6d\r"), iteration + 1);
- debug("\n");
- if (alt_test) {
- errs = mem_test_alt(buf, start, end, dummy);
- } else {
- errs = mem_test_quick(buf, start, end, pattern,
- iteration);
+// debug("\n");
+
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ my_puts_P(PSTR("Bus timeout\n"));
+ return CMD_RET_FAILURE;
}
- if (errs == -1UL)
+ errs += mem_test_alt(start, end);
+ z80_bus_cmd(Release);
+
+ if (had_ctrlc() || ctrlc()) {
break;
+ }
}
- if (errs == -1UL) {
+ if (had_ctrlc()) {
/* Memory test was aborted - write a newline to finish off */
- putc('\n');
- ret = 1;
+ putchar('\n');
+ ret = CMD_RET_FAILURE;
} else {
printf_P(PSTR("Tested %d iteration(s) with %lu errors.\n"),
iteration, errs);
- ret = errs != 0;
+ ret = errs ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
}
- return ret; /* not reached */
+ return ret;
}
#endif /* CONFIG_CMD_MEMTEST */
diff --git a/avr/cmd_misc.c b/avr/cmd_misc.c
index 315b959..c9a3c45 100644
--- a/avr/cmd_misc.c
+++ b/avr/cmd_misc.c
@@ -1,4 +1,6 @@
/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
* Copyright 2000-2009
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
@@ -7,46 +9,43 @@
#include "common.h"
#include <stdlib.h>
+#include <stdbool.h>
#include "command.h"
#include "timer.h"
#include "con-utils.h"
+#include "getopt-min.h"
command_ret_t do_echo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- uint_fast8_t putnl = 1;
+ bool put_newline = true;
(void) cmdtp; (void) flag;
- for (uint_fast8_t i = 1; i < argc; i++) {
+ /* reset getopt() */
+ optind = 1;
+
+ int opt;
+ while ((opt = getopt(argc, argv, PSTR("n"))) != -1) {
+ switch (opt) {
+ case 'n':
+ put_newline = false;
+ break;
+ default: /* '?' */
+ return CMD_RET_USAGE;
+ }
+ }
- uint_fast8_t backslash = 0;
- char *p = argv[i];
- char c;
+ for (uint_fast8_t i = optind; i < argc; i++) {
- if (i != 1)
+ if (i != optind)
putchar(' ');
- while ((c = *p++) != '\0') {
-
- if(backslash) {
- backslash = 0;
- if (c == 'c') {
- putnl = 0;
- continue;
- } else
- putchar('\\');
- } else {
- if (c == '\\') {
- backslash = 1;
- continue;
- }
- }
- putchar(c);
- }
+
+ my_puts(argv[i]);
}
- if (putnl)
+ if (put_newline)
putchar('\n');
return CMD_RET_SUCCESS;
@@ -88,4 +87,3 @@ command_ret_t do_sleep(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
return CMD_RET_SUCCESS;
}
-
diff --git a/avr/cmd_sd.c b/avr/cmd_sd.c
index 5494a13..6b75d6e 100644
--- a/avr/cmd_sd.c
+++ b/avr/cmd_sd.c
@@ -1,3 +1,9 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
#include "common.h"
#include <stdlib.h>
@@ -9,11 +15,11 @@
/*
- * di <pd#> - Initialize disk
+ * status <pd#> - Show socket status
*
*/
static
-command_ret_t do_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
DSTATUS res;
BYTE dev;
@@ -25,26 +31,50 @@ command_ret_t do_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
dev = (BYTE) strtoul(argv[1], 0, 10);
res = disk_status(dev);
- printf_P(PSTR("disk_status=%.2x\n"), res);
+ printf_P(PSTR("Socket status: %02x\n"), res);
+
+ return CMD_RET_SUCCESS;
+}
+
+/*
+ * init <pd#> - Initialize disk
+ *
+ */
+static
+command_ret_t do_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ DSTATUS res;
+ BYTE dev;
+
+ (void) cmdtp; (void) flag;
- if ((res & STA_NODISK) == 0) {
- res = disk_initialize(dev);
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ dev = (BYTE) strtoul(argv[1], 0, 10);
+
+ if (disk_status(dev) & STA_NODISK) {
+ printf_P(PSTR("No Disk\n"));
+ return CMD_RET_FAILURE;
}
+
+ res = disk_initialize(dev);
printf_P(PSTR("rc=%.2x\n"), res);
- if (res) {
+
+ if (res & (STA_NODISK | STA_NOINIT))
return CMD_RET_FAILURE;
- }
return CMD_RET_SUCCESS;
}
/*
- * ds <pd#> - Show disk status
+ * info <pd#> - Show disk info
*
*/
static
-command_ret_t do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+command_ret_t do_info(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
+ DSTATUS res;
BYTE dev;
union {
@@ -60,6 +90,12 @@ command_ret_t do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
dev = (BYTE) strtoul(argv[1], 0, 10);
+ res = disk_status(dev);
+ if (res & (STA_NODISK | STA_NOINIT)) {
+ printf_P(res & STA_NODISK ?
+ PSTR("No disk\n") : PSTR("Not initialized\n"));
+ return CMD_RET_FAILURE;
+ }
if (disk_ioctl(dev, GET_SECTOR_COUNT, &dat.ul) == RES_OK)
printf_P(PSTR("Drive size: %lu sectors\n"), dat.ul);
@@ -259,7 +295,7 @@ command_ret_t do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
/*
* Disk ioctl
- * dcs <pd#> - CTRL_SYNC
+ * sync <pd#> - CTRL_SYNC
*
*/
static
@@ -284,29 +320,34 @@ command_ret_t do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
cmd_tbl_t cmd_sd_sub[] = {
CMD_TBL_ITEM(
+ status, 2, 1, do_status,
+ "Socket staus",
+ ""
+),
+CMD_TBL_ITEM(
init, 2, 1, do_init,
"Initialize disk",
""
),
CMD_TBL_ITEM(
- status, 2, 1, do_status,
- "Disk status",
+ info, 2, 1, do_info,
+ "Disk info",
""
),
CMD_TBL_ITEM(
dump, CONFIG_SYS_MAXARGS, 1, do_dump,
- "Dump sector",
- ""
+ "Dump sector(s)",
+ "<drive> [sector [count ]]"
),
CMD_TBL_ITEM(
read, 2, 1, do_read,
- "read disk sector(s) into meomory",
- "drive [sector [count [memaddr]]]"
+ "Read disk sector(s) into meomory",
+ "<drive> [sector [count [memaddr]]]"
),
CMD_TBL_ITEM(
write, 2, 1, do_write,
- "write sector(s) from meomory to disk",
- "drive [sector [count [memaddr]]]"
+ "Write sector(s) from meomory to disk",
+ "<drive> [sector [count [memaddr]]]"
),
CMD_TBL_ITEM(
sync, 2, 1, do_ioctl_sync,
@@ -316,7 +357,7 @@ CMD_TBL_ITEM(
CMD_TBL_ITEM(
help, CONFIG_SYS_MAXARGS, 1, do_help,
- "print sub command description/usage",
+ "Print sub command description/usage",
"\n"
" - print brief description of all sub commands\n"
"sd help command ...\n"
@@ -325,7 +366,7 @@ CMD_TBL_ITEM(
/* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */
{FSTR("?"), CONFIG_SYS_MAXARGS, 1, do_help,
- FSTR("alias for 'help'"),
+ FSTR("Alias for 'help'"),
#ifdef CONFIG_SYS_LONGHELP
FSTR(""),
#endif /* CONFIG_SYS_LONGHELP */
diff --git a/avr/command.c b/avr/command.c
index c080527..ed25dee 100644
--- a/avr/command.c
+++ b/avr/command.c
@@ -1,4 +1,13 @@
/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * (C) Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
* Command Processor Table
*/
@@ -111,7 +120,7 @@ command_ret_t _do_help(cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp,
*/
for (i = 1; i < argc; ++i) {
if ((cmdtp = find_cmd_tbl (argv[i], cmd_start, cmd_items )) != NULL) {
- rcode = cmd_usage(cmdtp);
+ cmd_usage(cmdtp);
} else {
printf_P(PSTR("Unknown command '%s' - try 'help'"
" without arguments.\n\n"), argv[i]
@@ -140,8 +149,8 @@ cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len)
for (cmdtp = table;
cmdtp != table + table_len;
cmdtp++) {
- if (strncmp_P (cmd, cmdtp->name, len) == 0) {
- if (len == strlen (cmdtp->name))
+ if (strncmp_P(cmd, cmdtp->name, len) == 0) {
+ if (len == strlen_P(cmdtp->name))
return cmdtp; /* full match */
cmdtp_temp = cmdtp; /* abbreviated command ? */
diff --git a/avr/command_tbl.c b/avr/command_tbl.c
index 02d8ac8..72a87b9 100644
--- a/avr/command_tbl.c
+++ b/avr/command_tbl.c
@@ -1,10 +1,13 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
#include "common.h"
-
#include "command.h"
#include "cmd_mem.h"
-
extern command_ret_t do_help(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_echo(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_sleep(cmd_tbl_t *, int, int, char * const []);
@@ -13,10 +16,17 @@ extern command_ret_t do_env_default(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_env_set(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_env_save(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_loadf(cmd_tbl_t *, int, int, char * const []);
+extern command_ret_t do_loadcpm3(cmd_tbl_t *, int, int, char * const []);
+extern command_ret_t do_loadihex(cmd_tbl_t *, int, int, char * const []);
+#if defined(CONFIG_CMD_LOADB)
+extern command_ret_t do_load_serial_bin(cmd_tbl_t *, int, int, char * const []);
+#endif
extern command_ret_t do_go(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_restart(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_console(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_dump_mem(cmd_tbl_t *, int, int, char * const []);
+extern command_ret_t do_mem_mm_avr(cmd_tbl_t *, int, int, char * const []);
+extern command_ret_t do_mem_nm_avr(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_eep_cp(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_busreq_pulse(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_date(cmd_tbl_t *, int, int, char * const []);
@@ -24,8 +34,9 @@ extern command_ret_t do_gpio(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_sd(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_fat_stat(cmd_tbl_t *, int, int, char * const []);
extern command_ret_t do_fat_ls(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_fat_read(cmd_tbl_t *, int, int, char * const []);
-extern command_ret_t do_fat_write(cmd_tbl_t *, int, int, char * const []);
+//extern command_ret_t do_fat_read(cmd_tbl_t *, int, int, char * const []);
+//extern command_ret_t do_fat_write(cmd_tbl_t *, int, int, char * const []);
+extern command_ret_t do_fat_rw(cmd_tbl_t *, int, int, char * const []);
#ifdef CONFIG_SYS_LONGHELP
const FLASH char sd_help_text[] =
@@ -38,14 +49,14 @@ cmd_tbl_t cmd_tbl[] = {
CMD_TBL_ITEM(
date, 2, 1, do_date,
- "get/set/reset date & time",
+ "get/set date & time",
"[MMDDhhmm[[CC]YY][.ss]]\ndate reset\n"
" - without arguments: print date & time\n"
" - with numeric argument: set the system date & time\n"
- " - with 'reset' argument: reset the RTC"
),
#ifdef DEBUG
+
CMD_TBL_ITEM(
!mdr, 3, 1, do_dump_mem,
"RAM dump",
@@ -57,10 +68,25 @@ CMD_TBL_ITEM(
"address [count]"
),
CMD_TBL_ITEM(
+ !mdf, 3, 1, do_dump_mem,
+ "FLASH dump",
+ "address [count]"
+),
+CMD_TBL_ITEM(
!cpe, 4, 0, do_eep_cp,
"EEPROM copy",
"source target count"
),
+CMD_TBL_ITEM(
+ !mm, 2, 1, do_mem_mm_avr,
+ "avr memory modify (auto-incrementing address)",
+ "address"
+),
+CMD_TBL_ITEM(
+ !nm, 2, 1, do_mem_nm_avr,
+ "avr memory modify (constant address)",
+ "address"
+),
#endif
CMD_TBL_ITEM(
mstep, 2, 1, do_busreq_pulse,
@@ -70,9 +96,10 @@ CMD_TBL_ITEM(
),
CMD_TBL_ITEM(
echo, CONFIG_SYS_MAXARGS, 1, do_echo,
- "echo args to console",
- "[args..]\n"
- " - echo args to console; \\c suppresses newline"
+ "display a line of text",
+ "[-n] [argument ...]\n"
+ " - echo the argument(s) to console.\n"
+ " -n do not output the trailing newline"
),
CMD_TBL_ITEM(
sleep , 2, 1, do_sleep,
@@ -122,6 +149,43 @@ CMD_TBL_ITEM(
""
),
CMD_TBL_ITEM(
+ loadcpm3, 3, 0, do_loadcpm3,
+ "load CPM3.SYS file",
+ "[filename] [common base] [banked base]] \n"
+ " Load CP/M 3 system file from FAT filesystem. This command makes\n"
+ " CPMLDR superfluous. Uses the following environment variable if set:\n"
+ " '"ENV_CPM3_SYSFILE"' File to load. Default is '"CONFIG_CPM3_SYSFILE"'.\n"
+ " '"ENV_CPM3_COMMON_BASE"' Default is '"CONFIG_CPM3_COMMON_BASE_STR"'.\n"
+ " '"ENV_CPM3_BANKED_BASE"' Default is '"CONFIG_CPM3_BANKED_BASE_STR"'.\n"
+),
+CMD_TBL_ITEM(
+ loadi, 2, 0, do_loadihex,
+ "load intel hex file over serial line",
+ "[[-]offset]\n"
+ " - load Intel-Hex-Record file over serial line with offset 'offset'"
+),
+
+#if defined(CONFIG_CMD_LOADB)
+CMD_TBL_ITEM(
+ loadb, 1, 0, do_load_serial_bin,
+ "load binary file over serial line (kermit mode)",
+ " - load binary file over serial line"
+),
+
+CMD_TBL_ITEM(
+ loadx, 1, 0, do_load_serial_bin,
+ "load binary file over serial line (xmodem mode)",
+ " - load binary file over serial line"
+),
+
+CMD_TBL_ITEM(
+ loady, 1, 0, do_load_serial_bin,
+ "load binary file over serial line (ymodem mode)",
+ " - load binary file over serial line"
+),
+#endif /* CONFIG_CMD_LOADB */
+
+CMD_TBL_ITEM(
go, 2, 0, do_go,
"start application at address 'addr'",
"addr\n"
@@ -140,7 +204,7 @@ CMD_TBL_ITEM(
""
),
CMD_TBL_ITEM(
- connect, 1, 1, do_console,
+ connect, 1, 0, do_console,
"Connect to CPU console i/o",
""
),
@@ -202,23 +266,21 @@ CMD_TBL_ITEM(
" - set address offset for memory commands to 'offset'"
),
CMD_TBL_ITEM(
- loop, 3, 1, do_mem_loop,
+ mloop, 3, 1, do_mem_loop,
"infinite loop on address range",
"address number_of_bytes"
),
-#ifdef CONFIG_LOOPW
CMD_TBL_ITEM(
- loopw, 4, 1, do_mem_loopw,
+ mloopw, 4, 1, do_mem_loopw,
"infinite write loop on address range",
"address number_of_bytes data_to_write"
),
-#endif /* CONFIG_LOOPW */
#ifdef CONFIG_CMD_MEMTEST
CMD_TBL_ITEM(
- mtest, 5, 1, do_mem_mtest,
+ mtest, 4, 1, do_mem_mtest,
"simple RAM read/write test",
- "[start [end [pattern [iterations]]]]"
+ "[start [end [iterations]]]"
),
#endif /* CONFIG_CMD_MEMTEST */
@@ -229,7 +291,7 @@ CMD_TBL_ITEM(
"address count delay(ms)"
),
CMD_TBL_ITEM(
- mwc, 4, 1, do_mem_mwc,
+ mwc, 4, 1, do_mem_mdc,
"memory write cyclic",
"address value delay(ms)"
),
@@ -254,7 +316,7 @@ CMD_TBL_ITEM(
"path"
),
CMD_TBL_ITEM(
- fatload, 5, 0, do_fat_read,
+ fatload, 5, 0, do_fat_rw,
"load binary file from a dos filesystem",
"<d:/path/filename> <addr> [bytes [pos]]\n"
" - Load binary file 'path/filename' on logical drive 'd'\n"
@@ -265,11 +327,12 @@ CMD_TBL_ITEM(
" the load stops on end of file."
),
CMD_TBL_ITEM(
- fatwrite, 4, 0, do_fat_write,
+ fatwrite, 4, 0, do_fat_rw,
"write file into a dos filesystem",
"<d:/path/filename> <addr> <bytes>\n"
- " - write file 'filename' from the address 'addr' in RAM\n"
- " to 'dev' on 'interface'"
+ " - Write file to 'path/filename' on logical drive 'd' from RAM\n"
+ " starting at address 'addr'. 'bytes' gives the size to load.\n"
+ " If 'bytes' is 0 or omitted, the load stops on end of file."
),
CMD_TBL_ITEM(
diff --git a/avr/con-utils.c b/avr/con-utils.c
index f4023ff..5ee1ff1 100644
--- a/avr/con-utils.c
+++ b/avr/con-utils.c
@@ -1,7 +1,14 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
-#include <string.h>
#include "common.h"
+#include <string.h>
+#include <avr/wdt.h>
+#include "config.h"
#include "serial.h"
#include "background.h"
#include "con-utils.h"
@@ -21,6 +28,31 @@ int my_getchar(uint_fast8_t waitforchar)
c = serial_getc();
} while ((c < 0) && waitforchar);
+#ifdef CONFIG_SYS_FBOOTSIG
+ if (c < 0)
+ return c;
+
+ static const FLASH unsigned char bootsig[] = {CONFIG_SYS_FBOOTSIG};
+ static uint8_t pb;
+ unsigned char uc = c;
+
+
+ if (bootsig[pb] == 0) {
+ if (uc == 0xff) {
+ wdt_enable(WDTO_15MS);
+ for(;;)
+ ;
+ } else
+ pb = 0;
+
+ } else {
+ if (bootsig[pb] == uc)
+ pb++;
+ else
+ pb = 0;
+ }
+#endif
+
return c;
}
diff --git a/avr/date.c b/avr/date.c
deleted file mode 100644
index c85361f..0000000
--- a/avr/date.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * (C) Copyright 2001
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-/*
- * Date & Time support for RTC
- */
-
-#include <common.h>
-#include <command.h>
-#include <rtc.h>
-
-
-#define FEBRUARY 2
-#define STARTOFTIME 1970
-#define SECDAY 86400L
-#define SECYR (SECDAY * 365)
-#define leapyear(year) ((year) % 4 == 0)
-#define days_in_year(a) (leapyear(a) ? 366 : 365)
-#define days_in_month(a) (month_days[(a) - 1])
-
-
-static const FLASH int MonthOffset[] = {
- 0,31,59,90,120,151,181,212,243,273,304,334
-};
-
-/*
- * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
- */
-void GregorianDay(struct rtc_time * tm)
-{
- int leapsToDate;
- int lastYear;
- int day;
-
- lastYear=tm->tm_year-1;
-
- /*
- * Number of leap corrections to apply up to end of last year
- */
- leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
-
- /*
- * This year is a leap year if it is divisible by 4 except when it is
- * divisible by 100 unless it is divisible by 400
- *
- * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
- */
- if((tm->tm_year%4==0) &&
- ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
- (tm->tm_mon>2)) {
- /*
- * We are past Feb. 29 in a leap year
- */
- day=1;
- } else {
- day=0;
- }
-
- day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday;
-
- tm->tm_wday=day%7;
-}
-
-void to_tm(unsigned long tim, struct rtc_time * tm)
-{
- char month_days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
- register int i;
- register long hms, day;
-
- day = tim / SECDAY;
- hms = tim % SECDAY;
-
- /* Hours, minutes, seconds are easy */
- tm->tm_hour = hms / 3600;
- tm->tm_min = (hms % 3600) / 60;
- tm->tm_sec = (hms % 3600) % 60;
-
- /* Number of years in days */
- for (i = STARTOFTIME; day >= days_in_year(i); i++) {
- day -= days_in_year(i);
- }
- tm->tm_year = i;
-
- /* Number of months in days left */
- if (leapyear(tm->tm_year)) {
- days_in_month(FEBRUARY) = 29;
- }
- for (i = 1; day >= days_in_month(i); i++) {
- day -= days_in_month(i);
- }
- days_in_month(FEBRUARY) = 28;
- tm->tm_mon = i;
-
- /* Days are what is left over (+1) from all that. */
- tm->tm_mday = day + 1;
-
- /*
- * Determine the day of week
- */
- GregorianDay(tm);
-}
-
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
- * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
- * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
- *
- * [For the Julian calendar (which was used in Russia before 1917,
- * Britain & colonies before 1752, anywhere else before 1582,
- * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
- *
- * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
- */
-unsigned long
-mktime (unsigned int year, unsigned int mon,
- unsigned int day, unsigned int hour,
- unsigned int min, unsigned int sec)
-{
- if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
- mon += 12; /* Puts Feb last since it has leap day */
- year -= 1;
- }
-
- return (((
- (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
- year*365 - 719499
- )*24 + hour /* now have hours */
- )*60 + min /* now have minutes */
- )*60 + sec; /* finally seconds */
-}
-
diff --git a/avr/debug.c b/avr/debug.c
index 27b5329..f3632c2 100644
--- a/avr/debug.c
+++ b/avr/debug.c
@@ -1,3 +1,9 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
#include "common.h"
#include <stdlib.h>
#include <string.h>
@@ -5,8 +11,10 @@
#include <avr/eeprom.h>
#include "command.h"
+#include "cli_readline.h"
#include "print-utils.h"
#include "debug.h"
+
/*
* Debugging
*/
@@ -32,7 +40,7 @@ void dump_heap(void)
*/
command_ret_t do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- void (*readhow)(uint8_t *buf, uint32_t addr, uint8_t count);
+ void (*readwhat)(uint8_t *buf, uint32_t addr, uint8_t count);
(void) cmdtp; (void) flag;
@@ -42,12 +50,19 @@ command_ret_t do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
uint32_t addr;
uint32_t length = 128;
- if (strchr(argv[0],'r') != NULL)
- readhow = ram_read_buf;
- else if (strchr(argv[0],'e') != NULL)
- readhow = eeprom_read_buf;
- else
+ switch (argv[0][3]) {
+ case 'r':
+ readwhat = ram_read_buf;
+ break;
+ case 'e':
+ readwhat = eeprom_read_buf;
+ break;
+ case 'f':
+ readwhat = flash_read_buf;
+ break;
+ default:
return CMD_RET_USAGE;
+ }
/* Address is specified since argc > 1 */
addr = strtoul(argv[1], NULL, 16);
@@ -57,7 +72,7 @@ command_ret_t do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
length = (uint16_t) strtoul(argv[2], NULL, 16);
/* Print the lines. */
- dump_mem(addr, addr, length, readhow, NULL);
+ dump_mem(addr, addr, length, readwhat, NULL);
return CMD_RET_SUCCESS;
}
@@ -112,8 +127,85 @@ command_ret_t do_eep_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
return CMD_RET_SUCCESS;
}
-/*------------------------------------------------------------------------------*/
+/* Modify memory.
+ *
+ * Syntax:
+ * !mm {addr}
+ * !nm {addr}
+ */
+
+ static uint8_t *mm_last_addr;
+
+static command_ret_t
+mod_mem_avr(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
+{
+ uint8_t *addr;
+ uint8_t data;
+ int nbytes;
+
+ (void) cmdtp;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ /* We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ addr = mm_last_addr;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ /* New command specified.
+ */
+
+ /* Address is specified since argc > 1
+ */
+ addr = (uint8_t *) (size_t) strtoul(argv[1], NULL, 16);
+ }
+
+ /* Print the address, followed by value. Then accept input for
+ * the next value. A non-converted value exits.
+ */
+ do {
+ data = *addr;
+ printf_P(PSTR("%04x: %02x"), addr, data);
+
+ nbytes = cli_readline(PSTR(" ? "));
+ if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
+ /* <CR> pressed as only input, don't modify current
+ * location and move to next. "-" pressed will go back.
+ */
+ if (incrflag)
+ addr += nbytes ? -1 : 1;
+ nbytes = 1;
+
+ } else {
+ char *endp;
+ data = strtoul(console_buffer, &endp, 16);
+ nbytes = endp - console_buffer;
+ if (nbytes) {
+ *addr = data;
+ if (incrflag)
+ addr++;
+ }
+ }
+ } while (nbytes);
+
+ mm_last_addr = addr;
+ return CMD_RET_SUCCESS;
+}
+
+
+command_ret_t do_mem_mm_avr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ return mod_mem_avr (cmdtp, 1, flag, argc, argv);
+}
+command_ret_t do_mem_nm_avr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ return mod_mem_avr (cmdtp, 0, flag, argc, argv);
+}
+
+/*------------------------------------------------------------------------------*/
#if 1
diff --git a/avr/env.c b/avr/env.c
index 017053c..9ea355f 100644
--- a/avr/env.c
+++ b/avr/env.c
@@ -1,3 +1,9 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
#include "common.h"
#include <string.h>
#include <stdlib.h>
@@ -8,7 +14,6 @@
#include "xmalloc.h"
#include "crc.h"
#include "command.h"
-
#include "env.h"
@@ -26,13 +31,17 @@
#define DELIM "\0"
const FLASH char default_env[] = {
- "bootdelay=" "3" DELIM
- "bootcmd=" "reset; loadf; go ${startaddr}" DELIM
- "baudrate=" "115200" DELIM
- "startaddr=" "0" DELIM
+ ENV_BAUDRATE "=" "115200" DELIM
+ ENV_BOOTDELAY "=" "3" DELIM
+ ENV_BOOTCMD "=" "reset; loadf; go ${startaddr}" DELIM
+ ENV_CPM3_SYSFILE "=" CONFIG_CPM3_SYSFILE DELIM
+ ENV_PINALIAS "=" "0:PG5,1:PG4,2:PB4,3:PB5,4:PB6,5:PB7,"
+ "6:PG3,7:PG2,8:PG1,9:PG0,10:PE7" DELIM
+ ENV_STARTADDRESS "=" "0" DELIM
DELIM
};
+
/* EEPROM storage */
typedef struct environment_s {
uint16_t crc; /* CRC16 over data bytes */
@@ -447,7 +456,6 @@ command_ret_t _do_env_set(int flag, int argc, char * const argv[])
env_item_t e, *ep;
(void) flag;
- debug("Initial value for argc=%d\n", argc);
name = argv[1];
value = argv[2];
@@ -514,15 +522,35 @@ command_ret_t _do_env_set(int flag, int argc, char * const argv[])
* @return 0 if ok, 1 on error
*/
static
-int setenv(const char *varname, const char *varvalue)
+int setenv(const MEMX char *varname, const char *varvalue)
{
- const char * const argv[3] = { NULL, varname, varvalue };
+ int rc;
+
+#ifdef __MEMX
+ char *tmpname = NULL;
+ if (__builtin_avr_flash_segment(varname) != -1) {
+ tmpname = malloc(strlen_P(varname)+1);
+ if (tmpname == NULL) {
+ printf_P(PSTR("setenv: Out of Memory!\n"));
+ return 1;
+ }
+ strcpy_P(tmpname, varname);
+ } else
+ tmpname = (char *) varname;
+#endif
+
+ const char * const argv[3] = { NULL, tmpname, varvalue };
int argc = 3;
if (varvalue == NULL || varvalue[0] == '\0')
--argc;
- return (int) _do_env_set(0, argc, (char * const *)argv);
+ rc = (int) _do_env_set(0, argc, (char * const *)argv);
+
+#ifdef __MEMX
+ free(tmpname);
+#endif
+ return rc;
}
/**
diff --git a/avr/getopt-min.c b/avr/getopt-min.c
index 8e5dd6c..f5ad912 100644
--- a/avr/getopt-min.c
+++ b/avr/getopt-min.c
@@ -1,6 +1,3 @@
-#include "common.h"
-
-
/*
* Minimum getopt, original version was:
*/
@@ -13,7 +10,8 @@
*/
/* $Id: getopt.c,v 1.2 1992/12/07 11:12:52 nickc Exp $ */
-#include <string.h>
+#include "common.h" /* definition of FLASH */
+#include <string.h>
int optind = 1; /* next argv[] index */
char *optarg; /* option parameter if any */
@@ -40,7 +38,7 @@ getopt( /* returns letter, '?', EOF */
)
return -1;
}
-
+
c = argv[optind][sp]; /* option letter */
osp = sp++; /* get ready for next letter */
@@ -72,4 +70,3 @@ getopt( /* returns letter, '?', EOF */
return c;
}
-
diff --git a/avr/gpio.c b/avr/gpio.c
index 3c47247..73e9c39 100644
--- a/avr/gpio.c
+++ b/avr/gpio.c
@@ -1,42 +1,46 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
#include "common.h"
#include <util/atomic.h>
#include <limits.h>
#include "debug.h"
#include "gpio.h"
-
/*
-Pin Name Port Timer Mode max div max div min f [Hz]
-----------------------------------------------------------------------------------
-0 PG5 OC0B PWM (2**8)*1024 262144 70.31
-1 PG4
-2 CLK2 PB4 OC2A Toggle (2**8)*1024*2 524288 35.16
-3 ZCLK PB5 OC1A PWM (2**16)*1024 67108864 0.2746
-4 PB6 OC1B PWM (2**16)*1024 67108864 0.2746
-5 PB7 OC0A Toggle (2**8)*1024*2 524288 35.16
-6 PG3
-7 PG2
-8 PG1
-9 PG0
-10 CLKO PE7
-
-
-pre Timer0 Timer1 Timer2
+Pin Name Port Timer Mode max div max div min f [Hz]
+--------------------------------------------------------------------------------
+0 PG5 OC0B PWM (2**8)*1024 262144 70.31
+1 PG4
+2 CLK2 PB4 OC2A Toggle (2**8)*1024*2 524288 35.16
+3 ZCLK PB5 OC1A PWM (2**16)*1024 67108864 0.2746
+4 PB6 OC1B PWM (2**16)*1024 67108864 0.2746
+5 PB7 OC0A Toggle (2**8)*1024*2 524288 35.16
+6 PG3
+7 PG2
+8 PG1
+9 PG0
+10 CLKO PE7
+--------------------------------------------------------------------------------
+
+
+pre Timer0 Timer1 Timer2
--------------------------------------------------
-0 0 0 0
-1 1 1 1
-2 8 x8 8 x8 8 x8
-3 64 x8 64 x8 32 x4
-4 256 x4 256 x4 64 x2
-5 1024 x4 1024 x4 128 x2
-6 256 x2
-7 1024 x4
+0 0 0 0
+1 1 1 1
+2 8 x8 8 x8 8 x8
+3 64 x8 64 x8 32 x4
+4 256 x4 256 x4 64 x2
+5 1024 x4 1024 x4 128 x2
+6 256 x2
+7 1024 x4
--------------------------------------------------
-
*/
-
#define PWMTOGGLE 0b01
#define PWMPOS 0b10
#define PWMNEG 0b11
@@ -312,7 +316,7 @@ int gpio_clockdiv_set(int pin, unsigned long divider)
top = ltop - 1;
- PING |= _BV(0); /* Debug */
+// PING |= _BV(0); /* Debug */
switch (timertype & TIMER) {
case TIMER0:
@@ -363,7 +367,7 @@ int gpio_clockdiv_set(int pin, unsigned long divider)
break;
}
- PING |= _BV(0); /* Debug */
+// PING |= _BV(0); /* Debug */
gpio_config(pin, OUTPUT_TIMER);
diff --git a/avr/i2c.c b/avr/i2c.c
index d181ff6..ae2f8da 100644
--- a/avr/i2c.c
+++ b/avr/i2c.c
@@ -1,3 +1,8 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
/*
* I2C (TWI) master interface.
@@ -371,6 +376,3 @@ int i2c_read(uint8_t chip, unsigned int addr, uint_fast8_t alen,
return !((rc & (XMIT_DONE|DATA_ACK)) == (XMIT_DONE|DATA_ACK));
}
-
-
-
diff --git a/avr/main.c b/avr/main.c
index 7e832bf..3852e75 100644
--- a/avr/main.c
+++ b/avr/main.c
@@ -1,15 +1,18 @@
/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include "common.h"
-
#include <avr/interrupt.h>
+#include <avr/wdt.h>
#include <stdlib.h>
#include <stdio.h>
#include "config.h"
-#include "debug.h"
+#include "ff.h"
#include "z80-if.h"
#include "i2c.h"
#include "con-utils.h"
@@ -18,14 +21,14 @@
#include "cli.h"
#include "env.h"
#include "z180-serv.h"
-#include "spi.h"
#include "gpio.h"
+#include "time.h"
+#include "rtc.h"
+#include "debug.h"
-static uint8_t mcusr;
+uint8_t mcusr __attribute__ ((section (".noinit")));
-/*--------------------------------------------------------------------------*/
#if DEBUG
-
__attribute__ ((naked)) __attribute__ ((section (".init3")))
void preset_ram (void)
{
@@ -33,6 +36,21 @@ void preset_ram (void)
*p = 0xdd;
}
+#endif
+
+__attribute__ ((naked)) __attribute__ ((section (".init3")))
+void get_mcusr (void)
+{
+ /* save and clear reset reason(s) */
+ /* TODO: move to init section? */
+ mcusr = MCUSR;
+ MCUSR = 0;
+
+ wdt_disable();
+}
+
+/*--------------------------------------------------------------------------*/
+#if DEBUG
static const FLASH char * const FLASH rreasons[] = {
FSTR("Power on"),
@@ -74,13 +92,6 @@ ISR(INT6_vect)
static
void setup_avr(void)
{
- /* save and clear reset reason(s) */
- /* TODO: move to init section? */
- mcusr = MCUSR;
- MCUSR = 0;
-
- /* WD */
-
/* CPU */
/* Disable JTAG Interface regardless of the JTAGEN fuse setting. */
@@ -110,13 +121,6 @@ void setup_avr(void)
TCCR3B = (0b01<<WGM32)|(0b001<<CS30); /* CTC Mode, Prescaler 1 */
TIMSK3 = _BV(OCIE3A); /* Enable TC2.oca interrupt */
- /* SPI as master */
- PRR0 &= ~_BV(PRSPI);
- SPI_DDR = (SPI_DDR & ~_BV(SPI_MISO))
- | _BV(SPI_MOSI) | _BV(SPI_SCK) | _BV(SPI_SS);
- SPI_PORT = (SPI_PORT & ~(_BV(SPI_MOSI) | _BV(SPI_SCK)))
- | _BV(SPI_SS);
-
/* INT5, INT6: falling edge */
EICRB = (EICRB & ~((0b11 << ISC50) | (0b11 << ISC60))) |
(0b10 << ISC50) | (0b10 << ISC60);
@@ -132,6 +136,27 @@ int reset_reason_is_power_on(void)
return (mcusr & _BV(PORF)) != 0;
}
+static
+void setup_system_time(void)
+{
+ struct tm rtc_time;
+
+ rtc_get(&rtc_time);
+ rtc_time.tm_isdst = 0;
+ set_system_time(mk_gmtime(&rtc_time) );
+}
+
+
+
+static void setup_fatfs(void)
+{
+ static FATFS FatFs0;
+ static FATFS FatFs1;
+
+ f_mount(&FatFs0, "0:", 0);
+ f_mount(&FatFs1, "1:", 0);
+}
+
/*--------------------------------------------------------------------------*/
/* Stored value of bootdelay, used by autoboot_command() */
@@ -228,10 +253,13 @@ void main_loop(void)
int main(void)
{
- setup_avr();
- z80_setup_bus();
+ extern void setup_mmc(void);
+
for (int i = 0; i < GPIO_MAX; i++)
gpio_config(i, INPUT_PULLUP);
+ setup_avr();
+ setup_mmc();
+ z80_setup_bus();
env_init();
if (reset_reason_is_power_on())
@@ -245,13 +273,9 @@ int main(void)
print_reset_reason();
#endif
-#if DEBUG
- unsigned long i_speed = getenv_ulong(PSTR("i2c_clock"), 10, CONFIG_SYS_I2C_CLOCK);
- debug("### Setting I2C clock Frequency to %lu Hz.\n", i_speed);
- i2c_init(i_speed);
-#else
i2c_init(CONFIG_SYS_I2C_CLOCK);
-#endif
+ setup_system_time();
+ setup_fatfs();
printf_P(PSTR("\nATMEGA1281+Z8S180 Stamp Monitor\n\n"));
diff --git a/avr/mmc.c b/avr/mmc.c
index d780fef..7c4da24 100644
--- a/avr/mmc.c
+++ b/avr/mmc.c
@@ -10,41 +10,43 @@
#include "timer.h"
#include "spi.h"
#include "diskio.h"
-//#include "debug.h"
+#include "debug.h"
#define MAX_DRV 2
/* Port Controls (Platform dependent) */
/* SD card socket connections */
-//#define SD_CD_0 SBIT(PORT,) /* Card detect switch */
+/* TODO: config.h cofig macros */
+
+//#define SD_CD_0 SBIT(PORT,) /* Card detect switch */
//#define SD_CD_0_IN SBIT(PIN,)
//#define SD_CD_0_DDR SBIT(DDR,)
-//#define SD_WP_0 SBIT(PORT,) /* Write protect switch */
+//#define SD_WP_0 SBIT(PORT,) /* Write protect switch */
//#define SD_WP_0_IN SBIT(PIN,)
//#define SD_WP_0_DDR SBIT(DDR,)
-#define SD_CS_0 SBIT(PORTB,0) /* Chip select pin */
+#define SD_CS_0 SBIT(PORTB,0) /* Chip select pin */
#define SD_CS_0_IN SBIT(PINB,0)
#define SD_CS_0_DDR SBIT(DDRB,0)
-#define SD_CD_1 SBIT(PORTG,3) /* Card detect switch */
-#define SD_CD_1_IN SBIT(PING,3)
-#define SD_CD_1_DDR SBIT(DDRG,3)
-//#define SD_WP_1 SBIT(PORTG,5) /* Write protect switch */
-#define SD_WP_1_IN SBIT(PING,5)
-#define SD_WP_1_DDR SBIT(DDRG,5)
+//#define SD_CD_1 SBIT(PORTG,3) /* Card detect switch */
+//#define SD_CD_1_IN SBIT(PING,3)
+//#define SD_CD_1_DDR SBIT(DDRG,3)
+
+//#define SD_WP_1 SBIT(PORTG,5) /* Write protect switch */
+//#define SD_WP_1_IN SBIT(PING,5)
+//#define SD_WP_1_DDR SBIT(DDRG,5)
#define SD_CS_1 SBIT(PORTG,4) /* Chip select pin */
#define SD_CS_1_IN SBIT(PING,4)
#define SD_CS_1_DDR SBIT(DDRG,4)
-#define FCLK_SLOW() SPISetMMCInitClock() /* Set slow clock (100k-400k) */
-#define FCLK_FAST() SPISetFastClock() /* Set fast clock (depends on the CSD) */
-
+#define SPI_CLK_SLOW() SPISetMMCInitClock() /* Set slow clock (100k-400k) */
+#define SPI_CLK_FAST() SPISetFastClock() /* Set fast clock (depends on the CSD) */
/*--------------------------------------------------------------------------
Definitions for MMC/SDC command
@@ -113,14 +115,33 @@ int wait_ready (void) /* 1:OK, 0:Timeout */
static
void deselect(BYTE drv)
{
-// debug("*** enter deselect()\n");
+ //debug("*** enter deselect()\n");
if (drv == 0)
SD_CS_0 = 1;
- else
+ else {
SD_CS_1 = 1;
+ }
+
/* Dummy clock (TODO: force DO hi-z for multiple slave SPI) */
+ if (socket[drv].stat & STA_FAST)
+ SPI_CLK_FAST();
+ else
+ SPI_CLK_SLOW();
spi_rcvr();
-// debug("*** exit deselect()\n");
+ SPI_OFF();
+
+ if (drv == 0) {
+#ifdef SD_CS_0_IN
+ SD_CS_0_DDR = 0;
+ SD_CS_0 = 0;
+#endif
+ } else {
+#ifdef SD_CS_1_IN
+ SD_CS_1_DDR = 0;
+ SD_CS_1 = 0;
+#endif
+ }
+ //debug("*** exit deselect()\n");
}
/*-----------------------------------------------------------------------*/
@@ -130,20 +151,35 @@ void deselect(BYTE drv)
static
int select(BYTE drv) /* 1:Successful, 0:Timeout */
{
-// debug("*** enter select()\n");
- if (drv == 0)
+ //debug("*** enter select()\n");
+ if (drv == 0) {
+#ifdef SD_CS_0_IN
+ SD_CS_0 = 1;
+ SD_CS_0_DDR = 1;
+#endif
SD_CS_0 = 0;
- else
+ } else {
+#ifdef SD_CS_1_IN
+ SD_CS_1 = 1;
+ SD_CS_1_DDR = 1;
+#endif
SD_CS_1 = 0;
+ }
+
+ if (socket[drv].stat & STA_FAST)
+ SPI_CLK_FAST();
+ else
+ SPI_CLK_SLOW();
+
/* Dummy clock (force DO enabled) */
spi_rcvr();
if (wait_ready()) {
-// debug("*** exit select() == 1\n");
+ //debug("*** exit select() == 1\n");
return 1; /* OK */
}
deselect(drv);
-// debug("*** exit select() == 0\n");
+ //debug("*** exit select() == 0\n");
return 0; /* Timeout */
}
@@ -157,57 +193,29 @@ int select(BYTE drv) /* 1:Successful, 0:Timeout */
static
void power_on(BYTE drv)
{
-// debug("*** enter power_on()\n");
+ //debug("*** enter power_on()\n");
if (drv == 0) {
#ifdef SD_PWR_0
- SD_PWR_0_DDR = 1; /* Turns on PWR pin as output */
SD_PWR_0 = 0; /* Drives PWR pin high */
-
- for (uint32_t to = get_timer(0); get_timer(to) < 30;)
- ; /* Wait for 30ms */
#endif
-#ifdef SD_CD_0
- /* Card detect, input with pullup */
- SD_CD_0_DDR = 0;
- SD_CD_0 = 1;
-#endif
-#ifdef SD_WP_0
- SD_WP_0_DDR = 0;
- SD_WP_0 = 1;
-#endif
- SD_CS_0 = 1;
- SD_CS_0_DDR = 1;
} else {
#ifdef SD_PWR_1
- SD_PWR_1_DDR = 1; /* Turns on PWR pin as output */
SD_PWR_1 = 0; /* Drives PWR pin high */
-
+#endif
+ }
+#if defined SD_PWR_0 || defined SD_PWR_1
for (uint32_t to = get_timer(0); get_timer(to) < 30;)
; /* Wait for 30ms */
#endif
-
-#ifdef SD_CD_1
- /* Card detect, input with pullup */
- SD_CD_1_DDR = 0;
- SD_CD_1 = 1;
-#endif
-#ifdef SD_WP_1
- SD_WP_1_DDR = 0;
- SD_WP_1 = 1;
-#endif
- SD_CS_1 = 1;
- SD_CS_1_DDR = 1;
- }
-
-// debug("*** exit power_on()\n");
+ //debug("*** exit power_on()\n");
}
static
void power_off(BYTE drv)
{
-// debug("*** enter power_off()\n");
+ //debug("*** enter power_off()\n");
select(drv); /* Wait for card ready */
deselect(drv);
@@ -221,7 +229,7 @@ void power_off(BYTE drv)
#endif
}
socket[drv].stat |= STA_NOINIT;
-// debug("*** exit power_off()\n");
+ //debug("*** exit power_off()\n");
}
#if 0
@@ -330,7 +338,7 @@ BYTE send_cmd ( /* Returns R1 resp (bit7==1:Send failed) */
} argtmp;
BYTE n, res;
-// debug("*** send_cmd( %.2x )\n", cmd);
+ //debug("*** send_cmd( %.2x )\n", cmd);
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
cmd &= 0x7F;
@@ -378,6 +386,55 @@ BYTE send_cmd ( /* Returns R1 resp (bit7==1:Send failed) */
---------------------------------------------------------------------------*/
+void setup_mmc(void)
+{
+#ifdef SD_PWR_0
+ SD_PWR_1 = 1; /* Drives PWR pin low */
+ SD_PWR_0_DDR = 1; /* Turns on PWR pin as output */
+#endif
+#ifdef SD_WP_0
+ SD_WP_0_DDR = 0;
+ SD_WP_0 = 1; /* Pullup */
+#endif
+
+#ifdef SD_PWR_1
+ SD_PWR_1 = 1; /* Drives PWR pin low */
+ SD_PWR_1_DDR = 1; /* Turns on PWR pin as output */
+#endif
+#ifdef SD_WP_1
+ SD_WP_1_DDR = 0;
+ SD_WP_1 = 1; /* Pullup */
+#endif
+
+ /* SPI as master */
+ PRR0 &= ~_BV(PRSPI);
+ SPI_DDR = (SPI_DDR & ~(_BV(SPI_MISO) | _BV(SPI_SS)))
+ | _BV(SPI_MOSI) | _BV(SPI_SCK);
+ SPI_PORT = SPI_PORT & ~(_BV(SPI_MOSI) | _BV(SPI_SCK));
+
+#if defined SD_CD_0
+ SD_CD_0_DDR = 0;
+ SD_CD_0 = 1;
+#elif defined SD_CS_0_IN
+ SD_CS_0_DDR = 0;
+ SD_CS_0 = 0;
+#else
+ SD_CS_0_DDR = 1;
+ SD_CS_0 = 1;
+#endif
+
+#if defined SD_CD_1
+ SD_CD_1_DDR = 0;
+ SD_CD_1 = 1;
+#elif defined SD_CS_1_IN
+ SD_CS_1_DDR = 0;
+ SD_CS_1 = 0;
+#else
+ SD_CS_1_DDR = 1;
+ SD_CS_1 = 1;
+#endif
+}
+
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
@@ -393,10 +450,11 @@ DSTATUS disk_initialize (
if (drv >= MAX_DRV)
return STA_NOINIT; /* Supports only single drive */
if (socket[drv].stat & STA_NODISK)
- return socket[drv].stat; /* No card in the socket */
+ return socket[drv].stat & STAT_MASK; /* No card in the socket */
power_on(drv); /* Force socket power on */
- FCLK_SLOW();
+ socket[drv].stat &= ~STA_FAST;
+ SPI_CLK_SLOW();
for (n = 10; n; n--)
spi_rcvr(); /* 80 dummy clocks */
@@ -441,12 +499,13 @@ DSTATUS disk_initialize (
deselect(drv);
if (ty) { /* Initialization succeded */
- socket[drv].stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
+ /* Clear STA_NOINIT */
+ socket[drv].stat = (socket[drv].stat & ~STA_NOINIT) | STA_FAST;
} else { /* Initialization failed */
power_off(drv);
}
- return socket[drv].stat;
+ return socket[drv].stat & STAT_MASK;
}
/*-----------------------------------------------------------------------*/
@@ -459,7 +518,7 @@ DSTATUS disk_status (
{
if (drv >= MAX_DRV)
return STA_NOINIT;
- return socket[drv].stat;
+ return socket[drv].stat & STAT_MASK;
}
/*-----------------------------------------------------------------------*/
@@ -483,7 +542,6 @@ DRESULT disk_read (
/* Convert to byte address if needed */
if (!(socket[drv].CardType & CT_BLOCK))
sector *= 512;
- FCLK_FAST();
/* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
cmd = count > 1 ? CMD18 : CMD17;
@@ -523,7 +581,6 @@ DRESULT disk_write (
/* Convert to byte address if needed */
if (!(socket[drv].CardType & CT_BLOCK))
sector *= 512;
- FCLK_FAST();
if (count == 1) {
/* Single block write */
@@ -574,7 +631,8 @@ DRESULT disk_ioctl (
if (socket[drv].stat & STA_NOINIT)
return RES_NOTRDY;
- FCLK_FAST();
+ /* TODO: SPI clock? */
+
switch (cmd) {
case CTRL_SYNC : /* Make sure that no pending write process. Do not remove this or written sector might not left updated. */
if (select(drv))
@@ -682,29 +740,45 @@ void disk_timerproc (void)
#ifdef SD_WP_0
if (SD_WP_0_IN == 0) /* Write protected */
s |= STA_PROTECT;
- else /* Write enabled */
+ else /* Write enabled */
s &= ~STA_PROTECT;
#endif
-#ifdef SD_CD_0
+
+#if defined SD_CD_0
if (SD_CD_0_IN == 0) /* Card inserted */
s &= ~STA_NODISK;
- else /* Socket empty */
+ else /* Socket empty */
s |= (STA_NODISK | STA_NOINIT);
+#elif defined SD_CS_0_IN
+ if (SD_CS_0_DDR == 0) {
+ if (SD_CS_0_IN == 1) /* Card inserted */
+ s &= ~STA_NODISK;
+ else /* Socket empty */
+ s |= (STA_NODISK | STA_NOINIT);
+ }
#endif
- socket[0].stat = s; /* Update MMC status */
+ socket[0].stat = s; /* Update MMC status */
s = socket[1].stat;
#ifdef SD_WP_1
if (SD_WP_1_IN == 0) /* Write protected */
s |= STA_PROTECT;
- else /* Write enabled */
+ else /* Write enabled */
s &= ~STA_PROTECT;
#endif
-#ifdef SD_CD_1
+
+#if defined SD_CD_1
if (SD_CD_1_IN == 0) /* Card inserted */
s &= ~STA_NODISK;
- else /* Socket empty */
+ else /* Socket empty */
s |= (STA_NODISK | STA_NOINIT);
+#elif defined SD_CS_1_IN
+ if (SD_CS_1_DDR == 0) {
+ if (SD_CS_1_IN == 1) /* Card inserted */
+ s &= ~STA_NODISK;
+ else /* Socket empty */
+ s |= (STA_NODISK | STA_NOINIT);
+ }
#endif
socket[1].stat = s; /* Update MMC status */
}
diff --git a/avr/pcf8583.c b/avr/pcf8583.c
index af1331d..169e4e9 100644
--- a/avr/pcf8583.c
+++ b/avr/pcf8583.c
@@ -1,13 +1,20 @@
/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
* Date & Time support for Philips PCF8583 RTC
*/
#include "common.h"
#include <stdlib.h>
-#include "debug.h"
-#include "command.h"
+#include "time.h"
#include "rtc.h"
#include "i2c.h"
+#include "command.h"
+#include "debug.h"
#define DEBUG_RTC 0
@@ -34,17 +41,17 @@ static uint_fast8_t bcd2bin(uint8_t val)
static uint8_t bin2bcd (uint_fast8_t val)
{
div_t d = div(val, 10);
-
+
return (d.quot << 4) | d.rem;
}
-int rtc_get (struct rtc_time *tmp)
+int rtc_get (struct tm *tmp)
{
int rel = 0;
uint8_t rtcbuf[NR_OF_REGS];
- uint16_t year;
-
+ int16_t year;
+
i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, rtcbuf, NR_OF_REGS);
i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0x10, 1, (uint8_t *) &year, 2);
@@ -56,12 +63,12 @@ int rtc_get (struct rtc_time *tmp)
tmp->tm_min = bcd2bin (rtcbuf[REG_MIN] & 0x7F);
tmp->tm_hour = bcd2bin (rtcbuf[REG_HOUR] & 0x3F);
tmp->tm_mday = bcd2bin (rtcbuf[REG_YRDATE] & 0x3F);
- tmp->tm_mon = bcd2bin (rtcbuf[REG_WDMON] & 0x1F);
+ tmp->tm_mon = bcd2bin (rtcbuf[REG_WDMON] & 0x1F) - 1;
while (year%4 < (rtcbuf[REG_YRDATE]>>6)) {
year++;
/* TODO: update RTC ram */
}
- tmp->tm_year = year;
+ tmp->tm_year = year;
tmp->tm_wday = rtcbuf[REG_WDMON] >> 5;
tmp->tm_yday = 0;
tmp->tm_isdst= 0;
@@ -74,7 +81,7 @@ int rtc_get (struct rtc_time *tmp)
return rel;
}
-int rtc_set (struct rtc_time *tmp)
+int rtc_set (struct tm *tmp)
{
uint8_t rtcbuf[NR_OF_REGS];
@@ -84,7 +91,7 @@ int rtc_set (struct rtc_time *tmp)
rtcbuf[REG_CS] = 0x84;
rtcbuf[REG_CSEC] = 0x00;
- rtcbuf[REG_WDMON ] = bin2bcd(tmp->tm_mon) | ((tmp->tm_wday) << 5);
+ rtcbuf[REG_WDMON ] = (bin2bcd(tmp->tm_mon) + 1) | ((tmp->tm_wday) << 5);
rtcbuf[REG_YRDATE] = ((tmp->tm_year % 4) << 6) | bin2bcd(tmp->tm_mday);
rtcbuf[REG_HOUR ] = bin2bcd(tmp->tm_hour);
rtcbuf[REG_MIN ] = bin2bcd(tmp->tm_min);
diff --git a/avr/print-utils.c b/avr/print-utils.c
index 4205a90..9ce3e50 100644
--- a/avr/print-utils.c
+++ b/avr/print-utils.c
@@ -1,4 +1,11 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
#include "common.h"
+#include <stdint.h>
#include <stdio.h>
#include <ctype.h>
#include "con-utils.h"
@@ -22,6 +29,12 @@ void ram_read_buf(uint8_t *buf, uint32_t addr, uint8_t count)
*buf++ = *(uint8_t *) (size_t) addr++;
}
+void flash_read_buf(uint8_t *buf, uint32_t addr, uint8_t count)
+{
+ while (count--)
+ *buf++ = *(const __memx uint8_t *) (__uint24) addr++;
+}
+
int dump_mem(uint32_t address, uint32_t offset, uint32_t len,
void (*readfkt)(uint8_t *, uint32_t, uint8_t), char *title)
{
diff --git a/avr/serial.c b/avr/serial.c
index e897c84..adbc3c4 100644
--- a/avr/serial.c
+++ b/avr/serial.c
@@ -1,4 +1,7 @@
/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <avr/io.h>
@@ -12,7 +15,7 @@
static int _write(char c, FILE *stream);
-static FILE mystdout = FDEV_SETUP_STREAM(_write,
+static FILE mystdout = FDEV_SETUP_STREAM(_write,
NULL, _FDEV_SETUP_WRITE);
@@ -24,7 +27,7 @@ static FILE mystdout = FDEV_SETUP_STREAM(_write,
#endif
#if ((BUFFER_SIZE) > 256)
-# error: BUFFER_SIZE
+# error: BUFFER_SIZE
#endif
struct ring rx_ring;
@@ -119,5 +122,3 @@ uint_fast8_t serial_tstc(void)
{
return !ring_is_empty(&rx_ring);
}
-
-
diff --git a/avr/timer.c b/avr/timer.c
index 7907bba..f45f267 100644
--- a/avr/timer.c
+++ b/avr/timer.c
@@ -1,9 +1,13 @@
/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include "common.h"
#include <avr/interrupt.h>
#include <util/atomic.h>
+#include "time.h"
#include "timer.h"
/* timer interrupt/overflow counter */
@@ -11,14 +15,14 @@
static volatile
uint32_t timestamp;
-/*---------------------------------------------------------*/
-/* 1000Hz timer interrupt generated by OC3A */
-/*---------------------------------------------------------*/
-
+/*
+ * 1000Hz timer interrupt generated by OC3A
+ */
ISR(TIMER3_COMPA_vect)
{
static int_fast8_t tick_10ms;
- int_fast8_t i;
+ static int_fast8_t tick_1s;
+ int_fast8_t i, j;
extern void disk_timerproc(void);
@@ -26,11 +30,18 @@ ISR(TIMER3_COMPA_vect)
i = tick_10ms + 1;
if (i == 10) {
- i = 0;
Stat |= S_10MS_TO;
/* Drive timer procedure of low level disk I/O module */
disk_timerproc();
+
+ j = tick_1s - 1;
+ if (j == 0) {
+ system_tick();
+ j = 100;
+ }
+ tick_1s = j;
+ i = 0;
}
tick_10ms = i;
}
diff --git a/avr/xmalloc.c b/avr/xmalloc.c
index 9bf2684..d42d5c9 100644
--- a/avr/xmalloc.c
+++ b/avr/xmalloc.c
@@ -1,5 +1,10 @@
-#include <stdlib.h>
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <stdlib.h>
#include "debug.h"
#include "xmalloc.h"
@@ -11,7 +16,7 @@ void* xmalloc(size_t size)
if (p == NULL)
debug("*** Out of memory!\n");
-
+
return p;
}
@@ -22,6 +27,6 @@ void* xrealloc(void *p, size_t size)
if (p == NULL)
debug("*** Out of memory!\n");
-
+
return p;
}
diff --git a/avr/z180-serv.c b/avr/z180-serv.c
index e3bca16..69bcd9c 100644
--- a/avr/z180-serv.c
+++ b/avr/z180-serv.c
@@ -1,27 +1,32 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
#include "common.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
#include <util/atomic.h>
#include "background.h"
+#include "env.h"
+#include "ff.h"
#include "serial.h"
#include "z80-if.h"
#include "debug.h"
+#include "print-utils.h"
#include "z180-serv.h"
+#include "timer.h"
+#include "time.h"
+#include "bcd.h"
+#include "rtc.h"
+#define DEBUG_CPM_SDIO 0 /* set to 1 to debug */
-
-/*--------------------------------------------------------------------------*/
-
-
-uint8_t z80_get_byte(uint32_t adr)
-{
- uint8_t data;
-
- z80_bus_cmd(Request);
- data = z80_read(adr);
- z80_bus_cmd(Release);
-
- return data;
-}
+#define debug_cpmsd(fmt, args...) \
+ debug_cond(DEBUG_CPM_SDIO, fmt, ##args)
/*--------------------------------------------------------------------------*/
@@ -48,6 +53,25 @@ uint32_t msg_to_addr(uint8_t *msg)
}
+static int msg_xmit_header(uint8_t func, uint8_t subf, int len)
+{
+ z80_memfifo_putc(fifo_msgout, 0xAE);
+ z80_memfifo_putc(fifo_msgout, len+2);
+ z80_memfifo_putc(fifo_msgout, func);
+ z80_memfifo_putc(fifo_msgout, subf);
+
+ return 0;
+}
+
+int msg_xmit(uint8_t func, uint8_t subf, int len, uint8_t *msg)
+{
+ msg_xmit_header(func, subf, len);
+ while (len--)
+ z80_memfifo_putc(fifo_msgout, *msg++);
+
+ return 0;
+}
+
void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg)
{
(void)len;
@@ -64,6 +88,356 @@ void do_msg_char_out(uint8_t subf, int len, uint8_t * msg)
putchar(*msg++);
}
+/* echo message */
+void do_msg_echo(uint8_t subf, int len, uint8_t * msg)
+{
+ (void)subf;
+
+ /* send re-echo */
+ msg_xmit(1, 3, len, msg);
+}
+
+/* get timer */
+void do_msg_get_timer(uint8_t subf, int len, uint8_t * msg)
+{
+ uint32_t time_ms = (len >= 4) ? *(uint32_t *) msg : 0;
+
+ time_ms = get_timer(time_ms);
+ msg_xmit(3, subf, sizeof(time_ms), (uint8_t *) &time_ms);
+}
+
+/* ---------------------------------------------------------------------------*/
+
+#define CPM_DAY_OFFSET ((1978-1900) * 365 + 19) /* 19 leap years */
+
+/*
+ * Convert CP/M time stamp to a broken-down time structure
+ *
+ */
+int mk_date_time (int len, uint8_t *msg, struct tm *tmp)
+{
+ time_t stamp;
+
+ if (len != 5)
+ return -1;
+
+ /* days since 2000-01-01 */
+ long days = msg[3] + (msg[4] << 8) - 8036;
+
+ if (days < 0)
+ return -1;
+
+ stamp = days * ONE_DAY;
+ stamp += bcd2bin(msg[0]);
+ stamp += bcd2bin(msg[1]) * 60 ;
+ stamp += bcd2bin(msg[2]) * 3600L;
+ gmtime_r(&stamp, tmp);
+ return 0;
+}
+
+void mk_cpm_time(struct tm *tmp, uint8_t cpm_time[5])
+{
+ uint16_t days = 1;
+ uint_fast8_t leap=2;
+
+ for (int year=78; year < tmp->tm_year; year++) {
+ days = days + 365 + (leap == 0);
+ leap = (leap+1)%4;
+ }
+ days += tmp->tm_yday;
+
+ cpm_time[0] = bin2bcd(tmp->tm_sec);
+ cpm_time[1] = bin2bcd(tmp->tm_min);
+ cpm_time[2] = bin2bcd(tmp->tm_hour);
+ cpm_time[3] = days;
+ cpm_time[4] = days >> 8;
+}
+
+/* get/set cp/m time */
+void do_msg_get_set_time(uint8_t subf, int len, uint8_t * msg)
+{
+ struct tm t;
+ uint8_t cpm_time[5];
+ int rc;
+
+ memset(cpm_time, 0, ARRAY_SIZE(cpm_time));
+
+ switch (subf) {
+ case 3: /* set date & time */
+ /* initialize t with current time */
+ rc = rtc_get (&t);
+
+ if (rc == 0) {
+ /* insert new date & time */
+ if (mk_date_time (len, msg, &t) != 0) {
+ my_puts_P(PSTR("## set_time: Bad date format\n"));
+ break;
+ }
+
+ time_t time;
+ time = mk_gmtime(&t);
+ gmtime_r(&time, &t);
+
+ /* and write to RTC */
+ rc = rtc_set (&t);
+ if(rc)
+ my_puts_P(PSTR("## set_time: Set date failed\n"));
+ } else {
+ my_puts_P(PSTR("## set_time: Get date failed\n"));
+ }
+ /* FALL TROUGH */
+ case 2: /* get date & time */
+ rc = rtc_get (&t);
+
+ if (rc) {
+ my_puts_P(PSTR("## get_time: Get date failed\n"));
+ break;
+ }
+
+ time_t time;
+ time = mk_gmtime(&t);
+ //mktime(&t);
+ gmtime_r(&time, &t);
+
+
+ mk_cpm_time(&t, cpm_time);
+ break;
+ }
+
+ msg_xmit(3, subf, sizeof(cpm_time), cpm_time);
+}
+
+/* ---------------------------------------------------------------------------*/
+
+#define MAX_DRIVE 4
+#define BLOCK_SIZE 512
+//#define TPA_BASE 0x10000
+//#define COMMON_BASE 0xC000
+
+struct cpm_drive_s {
+ uint8_t drv;
+ uint8_t device;
+ char *img_name;
+ bool dirty;
+ FIL fd;
+};
+
+static uint8_t disk_buffer[BLOCK_SIZE];
+static struct cpm_drive_s drv_table[MAX_DRIVE];
+static int handle_cpm_drv_to;
+
+#define f_dirty(fp) ((fp)->fs->wflag != 0)
+
+
+int cpm_drv_to(int state)
+{
+ static uint32_t ts;
+
+ switch(state) {
+ case 0:
+ break;
+
+ case 1:
+ ts = get_timer(0);
+ state = 2;
+ break;
+
+ case 2:
+ if (get_timer(ts) > 1000) {
+ for (uint_fast8_t i=0; i < MAX_DRIVE; i++) {
+// if (&drv_table[i].fd && f_dirty(&drv_table[i].fd)) {
+ if (drv_table[i].dirty) {
+ f_sync(&drv_table[i].fd);
+ drv_table[i].dirty = false;
+ debug_cpmsd("## %7lu f_sync: %c:\n", get_timer(0), i+'A');
+ }
+ }
+ state = 0;
+ }
+ }
+ return state;
+}
+
+
+void msg_cpm_result(uint8_t subf, uint8_t rc, int res)
+{
+ uint8_t result_msg[3];
+
+ if (res)
+ rc |= 0x80;
+
+ result_msg[0] = rc;
+ result_msg[1] = res;
+ result_msg[2] = res >> 8;
+
+ if (rc) {
+ debug_cpmsd("###%7lu error rc: %.02x, res: %d\n", get_timer(0), rc, res);
+ }
+
+ msg_xmit(2, subf, sizeof(result_msg), result_msg);
+}
+
+/*
+ db 2 ; disk command
+ ds 1 ; subcommand (login/read/write)
+ ds 1 ; @adrv (8 bits) +0
+ ds 1 ; @rdrv (8 bits) +1
+ ds 3 ; @xdph (24 bits) +2
+*/
+
+void do_msg_cpm_login(uint8_t subf, int len, uint8_t * msg)
+{
+
+ FRESULT res = 0;
+ uint8_t drv;
+ char *np;
+
+ (void)subf;
+
+ if (len != 5) { /* TODO: check adrv, rdrv */
+ return msg_cpm_result(subf, 0x01, res);
+ }
+
+ debug_cpmsd("\n## %7lu login: %c:\n", get_timer(0), msg[0]+'A');
+
+
+ drv = msg[0];
+ if ( drv>= MAX_DRIVE) {
+ return msg_cpm_result(subf, 0x02, res);
+ }
+
+/*
+ uint32_t dph = ((uint32_t)msg[4] << 16) + ((uint16_t)msg[3] << 8) + msg[2];
+*/
+
+ if (drv_table[drv].img_name != NULL) {
+ debug_cpmsd("## %7lu close: '%s'\n", get_timer(0), drv_table[drv].img_name);
+ f_close(&drv_table[drv].fd);
+ drv_table[drv].dirty = false;
+ free(drv_table[drv].img_name);
+ drv_table[drv].img_name = NULL;
+ }
+
+ strcpy_P((char *)disk_buffer, PSTR("dsk0"));
+ disk_buffer[3] = msg[0] + '0';
+ if (((np = getenv((char*)disk_buffer)) == NULL) ||
+ ((drv_table[drv].img_name = strdup(np)) == NULL)) {
+ return msg_cpm_result(subf, 0x03, res);
+ }
+
+
+ res = f_open(&drv_table[drv].fd, drv_table[drv].img_name,
+ FA_WRITE | FA_READ);
+
+ debug_cpmsd("## %7lu open: '%s', (env: '%s'), res: %d\n", get_timer(0),
+ drv_table[drv].img_name, disk_buffer, res);
+
+ /* send result*/
+ msg_cpm_result(subf, 0x00, res);
+}
+
+
+/*
+ db 2 ; disk command
+ ds 1 ; subcommand (login/read/write)
+ ds 1 ; @adrv (8 bits) +0
+ ds 1 ; @rdrv (8 bits) +1
+ ds 2 ; @trk (16 bits) +2
+ ds 2 ; @sect(16 bits) +4
+ ds 1 ; @cnt (8 bits) +6
+ ds 3 ; phys. transfer addr +7
+*/
+
+#define ADRV 0
+#define RDRV 1
+#define TRK 2
+#define SEC 4
+#define CNT 6
+#define ADDR 7
+
+void do_msg_cpm_rw(uint8_t subf, int len, uint8_t * msg)
+{
+ uint8_t drv;
+ uint32_t addr;
+ uint32_t pos;
+ uint8_t secs;
+ bool dowrite = (subf == 2);
+ FRESULT res = 0;
+ uint8_t rc = 0;
+ bool buserr = 0;
+
+ if (len != 10) { /* TODO: check adrv, rdrv */
+ return msg_cpm_result(subf, 0x01, res);
+ }
+
+ drv = msg[ADRV];
+ if ( drv>= MAX_DRIVE) {
+ return msg_cpm_result(subf, 0x02, res);
+ }
+
+ secs = msg[CNT];
+ addr = ((uint32_t)msg[ADDR+2] << 16) + ((uint16_t)msg[ADDR+1] << 8) + msg[ADDR];
+
+
+ /* TODO: tracks per sector from dpb */
+ pos = (((uint16_t)(msg[TRK+1] << 8) + msg[TRK]) * 8
+ + ((uint32_t)(msg[SEC+1] << 8) + msg[SEC])) * BLOCK_SIZE;
+
+ debug_cpmsd("## %7lu cpm_rw: %s %c: trk:%4d, sec: %d, pos: %.8lx, secs: %2d, "
+ "addr: %.5lx\n", get_timer(0), dowrite ? "write" : " read",
+ msg[ADRV]+'A', ((uint16_t)(msg[TRK+1] << 8) + msg[TRK]), msg[SEC],
+ pos, msg[CNT], addr);
+
+ res = f_lseek(&drv_table[drv].fd, pos);
+ while (!res && secs--) {
+ unsigned int brw;
+ if (dowrite) {
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ buserr = 1;
+ break;
+ } else {
+ z80_read_block(disk_buffer, addr, BLOCK_SIZE);
+ z80_bus_cmd(Release);
+ }
+ res = f_write(&drv_table[drv].fd, disk_buffer, BLOCK_SIZE, &brw);
+ } else {
+ res = f_read(&drv_table[drv].fd, disk_buffer, BLOCK_SIZE, &brw);
+ if (res == FR_OK && brw == BLOCK_SIZE) {
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ buserr = 1;
+ break;
+ } else {
+ z80_write_block(disk_buffer, addr, BLOCK_SIZE);
+ z80_bus_cmd(Release);
+ }
+ }
+ }
+
+ if (brw != BLOCK_SIZE) {
+ debug_cpmsd("## %7lu f_read res: %d, bytes rd/wr: %u\n", get_timer(0), res, brw);
+ dump_ram(disk_buffer, 0, 64, "Read Data");
+ res = -1;
+ }
+
+ addr += BLOCK_SIZE;
+ }
+
+ if (dowrite && !res) {
+// res = f_sync(&drv_table[drv].fd);
+ drv_table[drv].dirty = true;
+ bg_setstat(handle_cpm_drv_to, 1);
+ }
+
+
+ if (buserr) {
+ debug_cpmsd("Bus timeout\n");
+ rc = 0x03;
+ }
+
+ /* send result*/
+ msg_cpm_result(subf, rc, res);
+}
+
const FLASH struct msg_item z80_messages[] =
{
@@ -73,6 +447,21 @@ const FLASH struct msg_item z80_messages[] =
{ 1,
1, 1,
do_msg_char_out},
+ { 1,
+ 2, 2,
+ do_msg_echo},
+ { 2,
+ 0, 0,
+ do_msg_cpm_login},
+ { 2,
+ 1, 2,
+ do_msg_cpm_rw},
+ { 3,
+ 1, 1,
+ do_msg_get_timer},
+ { 3,
+ 2, 3, /* 2: get, 3: set time and date */
+ do_msg_get_set_time},
{ 0xff, /* end mark */
0, 0,
0},
@@ -165,7 +554,7 @@ void check_msg_fifo(void)
int msg_handling(int state)
{
- uint8_t pending;
+ bool pending;
ATOMIC_BLOCK(ATOMIC_FORCEON) {
pending = (Stat & S_MSG_PENDING) != 0;
@@ -173,21 +562,27 @@ int msg_handling(int state)
}
if (pending) {
- switch (state) {
- case 0:
+ uint8_t init_request;
+ z80_bus_cmd(Request);
+ init_request = z80_read(0x43);
+ z80_bus_cmd(Release);
+ if ( init_request != 0) {
+ /* Get address of fifo 0 */
z80_bus_cmd(Request);
- uint32_t addr = z80_read(0x40) +
- ((uint16_t) z80_read(0x41) << 8) +
- ((uint32_t) z80_read(0x42) << 16);
+ uint32_t fifo_addr = z80_read(0x40) +
+ ((uint16_t) z80_read(0x40+1) << 8) +
+ ((uint32_t) z80_read(0x40+2) << 16);
+ z80_write(0x43, 0);
z80_bus_cmd(Release);
- if (addr != 0) {
- z80_memfifo_init(fifo_msgin, addr);
+
+ if (fifo_addr != 0) {
+ z80_memfifo_init(fifo_msgin, fifo_addr);
state = 1;
- }
- break;
- case 1:
+ } else
+ state = 0;
+
+ } else {
check_msg_fifo();
- break;
}
}
@@ -201,21 +596,22 @@ void setup_z180_serv(void)
{
handle_msg_handling = bg_register(msg_handling, 0);
+ handle_cpm_drv_to = bg_register(cpm_drv_to, 0);
}
void restart_z180_serv(void)
{
z80_bus_cmd(Request);
- z80_write(0x40, 0);
- z80_write(0x41, 0);
- z80_write(0x42, 0);
+ z80_memset(0x40, 0, 4);
z80_bus_cmd(Release);
for (int i = 0; i < NUM_FIFOS; i++)
z80_memfifo_init(i, 0);
bg_setstat(handle_msg_handling, 0);
+
}
+#if 0
/*--------------------------------------------------------------------------*/
const FLASH uint8_t iniprog[] = {
@@ -267,3 +663,4 @@ const FLASH uint8_t test1[] = {
0x00, // db 0 ;dst
0x00, 0x00, // dw 0 ;count (64k)
};
+#endif
diff --git a/avr/z180-stamp-avr.c b/avr/z180-stamp-avr.c
deleted file mode 100644
index e6edb33..0000000
--- a/avr/z180-stamp-avr.c
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- */
-
-
-#include <avr/io.h>
-//#include <avr/power.h>
-//#include <avr/pgmspace.h>
-#include <avr/interrupt.h>
-//#include <util/atomic.h>
-//#include <avr/sleep.h>
-//#include <string.h>
-
-#include <stdio.h>
-
-
-#include "debug.h"
-#include "serial.h"
-#include "z80-if.h"
-
-#define const const __flash
-#include "../z180/hdrom.h"
-#undef const
-
-#define FLASH __flash
-//#define FLASH
-
-#define ESCCHAR ('^'-0x40)
-
-#define S_10MS_TO (1<<0)
-
-
-volatile int_fast8_t timeout_1s;
-//volatile uint_least8_t Stat;
-#define Stat GPIOR0
-
-unsigned int to_counter;
-
-/****************************************************************/
-
-#define P_ADL PORTA
-#define P_ADH PORTC
-#define P_ADB PORTE
-#define PIN_ADB PINE
-
-#define ADB_WIDTH 3
-#define ADB_SHIFT 2
-//#define ADB_PORT GPIOE
-
-#define MASK(n) ((1<<(n))-1)
-#define SMASK(w,s) (MASK(w) << (s))
-
-typedef union {
- uint32_t l;
- uint16_t w[2];
- uint8_t b[4];
-} addr_t;
-
-
-
-/*--------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------*/
-/* 1000Hz timer interrupt generated by OC1A */
-/*---------------------------------------------------------*/
-
-ISR(TIMER1_COMPA_vect)
-{
- static int_fast8_t tick_10ms;
-// static int_fast16_t count_ms;
-
- int_fast8_t i;
-
-
- i = tick_10ms + 1;
- if (i == 10) {
- i = 0;
- Stat |= S_10MS_TO;
-
- /* Drive timer procedure of low level disk I/O module */
- //disk_timerproc();
- }
- tick_10ms = i;
-
-#if 0
- count_ms++;
- if (count_ms == 1000) {
- count_ms = 0;
-
- i = timeout_1s;
- if (i)
- timeout_1s = i - 1;
- }
-#endif
-}
-
-
-/*--------------------------------------------------------------------------*/
-
-static uint32_t z80_sram_cmp(uint32_t addr, uint32_t length, uint8_t wval, int inc)
-{
- uint8_t rval;
- int_fast8_t errors = 0;
-
- DBG_P(1, "SRAM: Check 0x%.5lx byte... ", length);
- while (length--) {
- if ((rval = z80_read(addr)) != wval) {
- if (errors == 0) {
- DBG_P(1, "\nSRAM: Address W R\n" \
- " ------------------\n");
- }
- errors++;
- if (errors > 20) {
- DBG_P(1, " ...\n");
- break;
- }
- DBG_P(1, " 0x%.5lx 0x%.2x 0x%.2x\n", addr, wval, rval);
- }
- addr++;
- wval += inc;
- }
- DBG_P(1, "Done.\n");
-
- return addr;
-}
-
-static void z80_sram_fill(uint32_t addr, uint32_t length, uint8_t startval, int inc)
-{
- printf("SRAM: Write 0x%.5lx byte... ", length);
- while (length--) {
- z80_write(addr, startval);
- ++addr;
- startval += inc;
- }
- printf("Done.\n");
-}
-
-
-#if 0
-void z80_sram_fill_string(uint32_t addr, int length, const char *text)
-{
- char c;
- const char *p = text;
-
- while (length--) {
- z80_write(addr++, c = *p++);
- if (c == 0)
- p = text;
- }
-}
-
-
-uint32_t z80_sram_cmp_string(uint32_t addr, int length, const char *text)
-{
- char c;
- const char *p = text;
-
- while (length--) {
- c = *p++;
- if (z80_read(addr) != c)
- break;
- ++addr;
- if (c == 0)
- p = text;
- }
- return addr;
-}
-
-const char * const qbfox = "Zhe quick brown fox jumps over the lazy dog!";
-const char * const qbcat = "Zhe quick brown fox jumps over the lazy cat!";
-
-#endif
-
-uint8_t z80_get_byte(uint32_t adr)
-{
- uint8_t data;
-
- z80_request_bus();
- data = z80_read(adr),
- z80_release_bus();
-
- return data;
-}
-
-
-/*--------------------------------------------------------------------------*/
-
-static void do_10ms(void)
-{
- if (to_counter)
- to_counter--;
-}
-
-/*--------------------------------------------------------------------------*/
-
-struct msg_item {
- uint8_t fct;
- uint8_t sub_min, sub_max;
- void (*func)(uint8_t, int, uint8_t *);
-};
-
-uint32_t msg_to_addr(uint8_t *msg)
-{
- union {
- uint32_t as32;
- uint8_t as8[4];
- } addr;
-
- addr.as8[0] = msg[0];
- addr.as8[1] = msg[1];
- addr.as8[2] = msg[2];
- addr.as8[3] = 0;
-
- return addr.as32;
-}
-
-void do_msg_ini_msgfifo(uint8_t subf, int len, uint8_t * msg)
-{
- (void)subf; (void)len;
-
- z80_init_msg_fifo(msg_to_addr(msg));
-}
-
-
-void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg)
-{
- (void)len;
-
- z80_memfifo_init(subf - 1, msg_to_addr(msg));
-}
-
-
-void do_msg_char_out(uint8_t subf, int len, uint8_t * msg)
-{
- (void)subf;
-
- while (len--)
- putchar(*msg++);
-}
-
-
-const FLASH struct msg_item z80_messages[] =
-{
- { 0, /* fct nr. */
- 0, 0, /* sub fct nr. from, to */
- do_msg_ini_msgfifo},
- { 0,
- 1, 2,
- do_msg_ini_memfifo},
- { 1,
- 1, 1,
- do_msg_char_out},
- { 0xff, /* end mark */
- 0, 0,
- 0},
-
-};
-
-
-
-
-void do_message(int len, uint8_t *msg)
-{
- uint8_t fct, sub_fct;
- int_fast8_t i = 0;
-
- if (len >= 2) {
- fct = *msg++;
- sub_fct = *msg++;
- len -= 2;
-
- while (fct != z80_messages[i].fct)
- ++i;
-
- if (z80_messages[i].fct == 0xff) {
- DBG_P(1, "do_message: Unknown function: %i, %i\n",
- fct, sub_fct);
- return; /* TODO: unknown message # */
- }
-
- while (fct == z80_messages[i].fct) {
- if (sub_fct >= z80_messages[i].sub_min && sub_fct <= z80_messages[i].sub_max )
- break;
- ++i;
- }
-
- if (z80_messages[i].fct != fct) {
- DBG_P(1, "do_message: Unknown sub function: %i, %i\n",
- fct, sub_fct);
- return; /* TODO: unknown message sub# */
- }
-
- (z80_messages[i].func)(sub_fct, len, msg);
-
-
- } else {
- /* TODO: error */
- DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len);
- }
-}
-
-
-
-#define CTRBUF_LEN 256
-
-void check_msg_fifo(void)
-{
- int ch;
- static int_fast8_t state;
- static int msglen,idx;
- static uint8_t buffer[CTRBUF_LEN];
-
- while (state != 3 && (ch = z80_msg_fifo_getc()) >= 0) {
- switch (state) {
- case 0: /* wait for start of message */
- if (ch == 0x81) {
- msglen = 0;
- idx = 0;
- state = 1;
- }
- break;
- case 1: /* get msg len */
- if (ch > 0 && ch <= CTRBUF_LEN) {
- msglen = ch;
- state = 2;
- } else
- state = 0;
- break;
- case 2: /* get message */
- buffer[idx++] = ch;
- if (idx == msglen)
- state = 3;
- break;
- }
- }
-
- if (state == 3) {
- do_message(msglen, buffer);
- state = 0;
- }
-}
-
-
-/*--------------------------------------------------------------------------*/
-
-void dump_mem(const __flash uint8_t *addr, uint32_t len)
-{
- DBG_P(1, "hdrom dump:");
- while (len) {
- DBG_P(1, "\n %.5x:", addr);
- for (unsigned i = 0; i<16; i++)
- DBG_P(1, " %.2x", *addr++);
- len -= len > 16 ? 16 : len;
- }
- DBG_P(1, "\n");
-}
-
-/*--------------------------------------------------------------------------*/
-
-void z80_load_mem(void)
-{
- unsigned sec = 0;
- uint32_t sec_base = hdrom_start;
-
- DBG_P(1, "Loading z80 memory... \n");
-
- while (sec < hdrom_sections) {
- DBG_P(2, " From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n",
- hdrom_address[sec],
- hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
- hdrom_length_of_sections[sec]);
-
- z80_write_block((const __flash unsigned char *) &hdrom[sec_base], /* src */
- hdrom_address[sec], /* dest */
- hdrom_length_of_sections[sec]); /* len */
- sec_base+=hdrom_length_of_sections[sec];
- sec++;
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-void z80_dump_mem(uint32_t addr, uint32_t len)
-{
- DBG_P(1, "Memory dump:");
- while (len) {
- DBG_P(1, "\n %.5lx:", addr);
- for (unsigned i = 0; i<16; i++)
- DBG_P(1, " %.2x", z80_read(addr++));
- len -= len > 16 ? 16 : len;
- }
- DBG_P(1, "\n");
-}
-
-/*--------------------------------------------------------------------------*/
-
-void setup_rtc(void)
-{
- /* TODO: */
-}
-
-void setup_avr(void)
-{
- /* WD */
-
- /* CPU */
-
- /* Disable JTAG Interface regardless of the JTAGEN fuse setting. */
- MCUCR = _BV(JTD);
- MCUCR = _BV(JTD);
-
- /* disable unused periphels */
- PRR0 = _BV(PRTIM2) | _BV(PRTIM0) | _BV(PRADC);
- PRR1 = _BV(PRTIM5) | _BV(PRTIM4) | _BV(PRTIM3) |
- _BV(PRUSART3) | _BV(PRUSART2) | _BV(PRUSART1);
-
- /* disable analog comparator */
- ACSR = _BV(ACD);
- /* Ports */
-
- /* Clock */
- CLKPR = _BV(CLKPCE);
- CLKPR = 0;
-
- /* Timer */
-
- OCR1A = F_CPU / 8 / 1000 - 1; // Timer1: 1000Hz interval (OC1A)
- TCCR1B = 0b00001010;
- TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt
-}
-
-const __flash uint8_t iniprog[] = {
- 0xAF, // xor a
- 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh
- 0x3E, 0x30, // ld a,030h
- 0xED, 0x39, 0x32 //out0 (dcntl),a ;0 mem, max i/0 wait states
-};
-
-const __flash uint8_t sertest[] = {
- 0xAF, // xor a
- 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh
- 0x3E, 0x30, // ld a,030h
- 0xED, 0x39, 0x32, // out0 (dcntl),a ;0 mem, max i/0 wait states
- 0x3E, 0x80, // ld a,M_MPBT ;no MP, PS=10, DR=16, SS=0
- 0xED, 0x39, 0x03, // out0 (cntlb1),a
- 0x3E, 0x64, // ld a,M_RE + M_TE + M_MOD2 ;
- 0xED, 0x39, 0x01, // out0 (cntla1),a
- 0x3E, 0x00, // ld a,0
- 0xED, 0x39, 0x05, // out0 (stat1),a ;Enable rx interrupts
- 0xED, 0x38, 0x05, //l0:in0 a,(stat1)
- 0xE6, 0x80, // and 80h
- 0x28, 0xF9, // jr z,l0
- 0xED, 0x00, 0x09, // in0 b,(rdr1)
- 0xED, 0x38, 0x05, //l1:in0 a,(stat1)
- 0xE6, 0x02, // and 02h
- 0x28, 0xF9, // jr z,l1
- 0xED, 0x01, 0x07, // out0 (tdr1),b
- 0x18, 0xEA, // jr l0
-};
-
-const __flash uint8_t test1[] = {
- 0xAF, // xor a
- 0xED, 0x39, 0x36, // out0 (rcr),a ;disable DRAM refresh
- 0x3E, 0x30, // ld a,030h
- 0xED, 0x39, 0x32, // out0 (dcntl),a ;0 mem, max i/0 wait states
- 0x21, 0x1E, 0x00, // ld hl,dmclrt ;load DMA registers
- 0x06, 0x08, // ld b,dmct_e-dmclrt
- 0x0E, 0x20, // ld c,sar0l
- 0xED, 0x93, // otimr
- 0x3E, 0xC3, // ld a,0c3h ;dst +1, src +1, burst
- 0xED, 0x39, 0x31, // out0 (dmode),a ;
- 0x3E, 0x62, // ld a,062h ;enable dma0,
- 0xED, 0x39, 0x30, //cl_1: out0 (dstat),a ;copy 64k
- 0x18, 0xFB, // jr cl_1 ;
- 0x00, 0x00, //dmclrt: dw 0 ;src (inc)
- 0x00, // db 0 ;src
- 0x00, 0x00, // dw 0 ;dst (inc),
- 0x00, // db 0 ;dst
- 0x00, 0x00, // dw 0 ;count (64k)
-};
-
-
-int main(void)
-{
- int_fast8_t state = 0;
- int ch;
-
- setup_avr();
- serial_setup();
- setup_rtc();
- sei();
-
- printf_P(PSTR("\n(ATMEGA1281+HD64180)_stamp Tester\n"));
-
- DBG_P(1, "z80_setup_bus... ");
- z80_setup_msg_fifo();
- z80_setup_bus();
- DBG_P(1, "done.\n");
-
- DBG_P(1, "Get bus... ");
-/* Now done via S_Z180_RUNNING
- z80_busreq(LOW);
- z80_reset(HIGH);
-*/
- z80_request_bus();
- DBG_P(1, "got it!\n");
-
-// z80_sram_fill(0, (uint32_t)512 * 1024, 0x00, 3);
-// z80_sram_cmp(0, (uint32_t)512 * 1024, 0x00, 3);
-// z80_dump_mem(0, 0x400);
-
- z80_memset(0, 0x76, 0x80000);
-// z80_memset(0, 0x00, 0x80000);
-// z80_write_block(test1, 0, sizeof(test1));
-
-// z80_dump_mem(0, 0x100);
-
-// z80_sram_cmp(0, (uint32_t)512 * 1024, 0x76, 0);
-
- z80_load_mem();
-// z80_write(0, 0x76);
-// z80_dump_mem(0, 0x200);
-
-
-/* Now done via S_Z180_RUNNING
- z80_reset(LOW);
-*/
- z80_release_bus();
- DBG_P(1, "Bus released!\n");
- z80_reset(HIGH);
- DBG_P(1, "Reset released!\n");
-
- to_counter = 200;
-
- while (1) {
-
- if (Stat & S_10MS_TO) {
- Stat &= ~S_10MS_TO;
- do_10ms();
- }
-
-
- if ((ch = serial_getc()) >= 0) {
- switch (state) {
- case 0:
- if (ch == ESCCHAR) {
- state = 1;
- /* TODO: Timer starten */
- } else {
-// z80_memfifo_putc(fifo_out, ch);
- serial_putc(ch);
- if (ch == '\r')
- serial_putc('\n');
- }
- break;
- case 1:
- switch (ch) {
-
- case 'r':
- z80_reset_pulse();
- break;
-
- case 'b':
- z80_request_bus();
- z80_dump_mem(0, 0x2d20);
- z80_release_bus();
- break;
-
- case 'e':
- z80_request_bus();
- z80_dump_mem(0x80000-0x4000, 0x800);
- z80_dump_mem(0x80000-0x200, 0x200);
- z80_release_bus();
- break;
-
- case ESCCHAR:
- default:
-// z80_memfifo_putc(fifo_out, ch);
- serial_putc(ch);
- if (ch == '\r')
- serial_putc('\n');
- }
- state = 0;
- break;
- }
- }
-
-// check_msg_fifo();
- }
-
- return 0;
-}
diff --git a/avr/z80-if.c b/avr/z80-if.c
index cc0bab1..21ffeac 100644
--- a/avr/z80-if.c
+++ b/avr/z80-if.c
@@ -1,3 +1,9 @@
+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
/**
*
* Pin assignments
@@ -50,7 +56,6 @@
* | | P | | af1 OSC32 |
* | | P | | af1 OSC32 |
-
*/
@@ -555,10 +560,9 @@ void z80_memfifo_init(const fifo_t f, uint32_t addr)
{
fifo_dsc[f].base = addr;
- if (addr != 0) {
-
DBG_P(2, "z80_memfifo_init: %i, %lx\n", f, addr);
+ if (addr != 0) {
z80_bus_cmd(Request);
fifo_dsc[f].mask = z80_read(addr + FIFO_BUFSIZE_MASK);
fifo_dsc[f].idx_in = z80_read(addr + FIFO_INDEX_IN);
@@ -588,7 +592,7 @@ int z80_memfifo_is_empty(const fifo_t f)
int z80_memfifo_is_full(const fifo_t f)
{
- int rc = 1;
+ int rc = 0;
if (fifo_dsc[f].base != 0) {
z80_bus_cmd(Request);