From 6035a17b2becc788c0daaf440deb6cc37d364029 Mon Sep 17 00:00:00 2001 From: Leo C Date: Mon, 8 Sep 2014 19:54:08 +0200 Subject: Programmable Z180 clock, clock command --- avr/cmd_boot.c | 49 +++++++++++++++---- avr/cmd_mem.c | 20 ++++---- avr/command_tbl.c | 6 +++ avr/z80-if.c | 141 +++++++++++++++++++++++++++++++++++++++--------------- include/z80-if.h | 7 ++- 5 files changed, 162 insertions(+), 61 deletions(-) diff --git a/avr/cmd_boot.c b/avr/cmd_boot.c index 3e2dcdb..58c4f56 100644 --- a/avr/cmd_boot.c +++ b/avr/cmd_boot.c @@ -44,13 +44,13 @@ 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) { + if (z80_bus_state() & ZST_RUNNING) { printf_P(PSTR("## Can't load while CPU is running!\n")); - return CMD_RET_FAILURE; + return CMD_RET_FAILURE; } z80_load_mem(); - + return CMD_RET_SUCCESS; } @@ -61,7 +61,7 @@ command_ret_t do_busreq_pulse(cmd_tbl_t *cmdtp, int flag, int argc, char * const (void) cmdtp; (void) flag; - if (!(z80_bus_state() & ZST_RUNNING)) { + if (!(z80_bus_state() & ZST_RUNNING)) { printf_P(PSTR("## CPU is not running!\n")); return CMD_RET_FAILURE; } @@ -82,7 +82,7 @@ command_ret_t do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) uint32_t addr; (void) cmdtp; (void) flag; - + if (argc < 2) return CMD_RET_USAGE; addr = strtoul(argv[1], NULL, 16); @@ -91,9 +91,9 @@ command_ret_t do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) " (Out of logical address space (0x00000-0x0ffff))\n"), addr); return CMD_RET_FAILURE; - } + } - if (z80_bus_state() & ZST_RUNNING) { + if (z80_bus_state() & ZST_RUNNING) { printf_P(PSTR("## CPU allready running!\n")); return CMD_RET_FAILURE; } @@ -103,7 +103,7 @@ command_ret_t do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (addr != 0) { uint8_t tmp[3]; uint_fast8_t i; - + z80_bus_cmd(Request); for (i = 0; i < 3; i++) tmp[i] = z80_read(i); @@ -118,7 +118,7 @@ command_ret_t do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) z80_write(i, tmp[i]); } else z80_bus_cmd(Run); - + z80_bus_cmd(Release); return CMD_RET_SUCCESS; @@ -143,3 +143,34 @@ command_ret_t do_restart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv return CMD_RET_SUCCESS; } + +command_ret_t do_clock(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + uint32_t freq; + + (void) cmdtp; (void) flag; + + if (argc == 2) { + freq = strtoul(argv[1], NULL, 10); + if (freq == 0) { + printf_P(PSTR("CPU clock cannot be 0\n")); + return CMD_RET_USAGE; + } + + if (freq > F_CPU / 2) { + printf_P(PSTR("Max CPU clock freq. is: %luHz\n"), F_CPU/2); + return CMD_RET_USAGE; + } + + if (z80_clock_set(freq) < 0) { + printf_P(PSTR("Setting CPU clock freq. to %luHz failed.\n"), + freq); + } + } + + printf_P(PSTR("CPU clock: %luHz\n"), z80_clock_get()); + + + return CMD_RET_SUCCESS; +} + diff --git a/avr/cmd_mem.c b/avr/cmd_mem.c index 91668bd..f1f34c0 100644 --- a/avr/cmd_mem.c +++ b/avr/cmd_mem.c @@ -22,9 +22,6 @@ #include "con-utils.h" #include "z80-if.h" -/* - * TODO: printf() --> printf_P() - */ #ifndef CONFIG_SYS_MEMTEST_SCRATCH #define CONFIG_SYS_MEMTEST_SCRATCH 0 @@ -55,10 +52,10 @@ int z180_dump_mem(uint32_t startaddr, uint32_t len, const char *title) uint32_t addr = startaddr & ~0x0f; len += pre; uint8_t i; - + if (title && *title) printf_P(PSTR("%s\n"),title); - + while (len) { if (len < 16) llen = len; @@ -117,10 +114,10 @@ int z180_dump_mem(uint32_t startaddr, uint32_t len, const char *title) command_ret_t do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { uint32_t addr, length; - + (void) cmdtp; -#if 0 +#if 0 printf_P(PSTR("flag: %d, argc: %d"), flag, argc); for (int i = 0; i < argc; i++) { printf_P(PSTR(", argv[%d]: %s"), i, argv[i] ? argv[i] : ""); @@ -264,7 +261,7 @@ command_ret_t do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[ z80_bus_cmd(Request); while (count-- > 0) { z80_write(addr, writeval); - ++addr; + ++addr; } z80_bus_cmd(Release); @@ -354,8 +351,8 @@ command_ret_t do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv byte2 = z80_read(addr2); z80_bus_cmd(Release); if (byte1 != byte2) { - printf( "byte at 0x%05lx (%#02x) != " - "byte at 0x%05lx (%#02x)\n", + printf_P(PSTR("byte at 0x%05lx (%#02x) != " + "byte at 0x%05lx (%#02x)\n"), addr1, byte1, addr2, byte2); rcode = CMD_RET_FAILURE; break; @@ -395,7 +392,7 @@ command_ret_t do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[ my_puts_P(PSTR("Zero length?\n")); return CMD_RET_FAILURE; } - + if (dest > src) { src += count - 1; dest += count - 1; @@ -875,4 +872,3 @@ command_ret_t do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, return ret; /* not reached */ } #endif /* CONFIG_CMD_MEMTEST */ - diff --git a/avr/command_tbl.c b/avr/command_tbl.c index 6e8a91b..c721d53 100644 --- a/avr/command_tbl.c +++ b/avr/command_tbl.c @@ -18,6 +18,7 @@ extern command_ret_t do_dump_mem(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 []); +extern command_ret_t do_clock(cmd_tbl_t *, int, int, char * const []); cmd_tbl_t cmd_tbl[] = { @@ -119,6 +120,11 @@ CMD_TBL_ITEM( "Perform RESET of the CPU", "" ), +CMD_TBL_ITEM( + clock, 2, 0, do_clock, + "Set or get CPU frequency", + "" +), CMD_TBL_ITEM( md, 3, 1, do_mem_md, diff --git a/avr/z80-if.c b/avr/z80-if.c index 726e50b..c0f128e 100644 --- a/avr/z80-if.c +++ b/avr/z80-if.c @@ -157,8 +157,87 @@ static zstate_t zstate; /*--------------------------------------------------------------------------*/ +static +void z80_setup_clock(void) +{ + /* ZCLK: Output and low */ + DDR_ZCLK |= _BV(ZCLK); + Z80_O_ZCLK = 0; + + DDRB |= _BV(6); /* Debug */ + PORTB |= _BV(6); /* Debug */ + + PRR0 &= ~_BV(PRTIM1); + + /* Timer1: CTC: Toggle OC1C on compare match */ + OCR1A = 0; + OCR1C = 0; + TCCR1A = (0b01 << COM1C0) | (0b00 << WGM10); + TCCR1B = (0b01 << WGM12) | (0b001 << CS10); +} -static void z80_setup_addrbus_tristate(void) + +int z80_clock_set(unsigned long freq) +{ + unsigned long ocrval = F_CPU / freq / 2; + uint8_t prescale = 0; + + while (ocrval > (1L<<16)) { + prescale++; + if (prescale < 3) + ocrval = ocrval / 8; + else + ocrval = ocrval / 4; + } + + if ((ocrval == 0) || (prescale > 4)) + return -1; + + ocrval -= 1; + + PINB |= _BV(6); /* Debug */ + + /* Stop Timer */ + TCCR1B = (0b01 << WGM12) | (0b000 << CS10); + TCNT1 = 0; + + OCR1A = ocrval; + OCR1CL = ocrval; + TCCR1A = (0b01 << COM1C0) | (0b00 << WGM10); + TCCR1B = (0b01 << WGM12) | ((prescale+1) << CS10); + + if (ocrval == 0) { +// TCCR1C |= _BV(FOC1C); + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + TCNT1 = 0xFFFF; + } + } + + PINB |= _BV(6); /* Debug */ + + return 0; +} + +uint32_t z80_clock_get(void) +{ + uint32_t count = (OCR1A + 1L) * 2; + uint8_t pre = (TCCR1B & 7) - 1; + + while (pre) { + if (pre > 2) + count *= 4; + else + count *= 8; + pre--; + + } + + return F_CPU/count; +} + + + +static void z80_addrbus_set_tristate(void) { /* /MREQ, /RD, /WR: Input, no pullup */ DDR_MREQ &= ~(_BV(MREQ) | _BV(RD) | _BV(WR)); @@ -175,7 +254,7 @@ static void z80_setup_addrbus_tristate(void) } -static void z80_setup_addrbus_active(void) +static void z80_addrbus_set_active(void) { /* /MREQ, /RD, /WR: Output and high */ Z80_O_MREQ = 1; @@ -189,14 +268,14 @@ static void z80_setup_addrbus_active(void) } -static void z80_setup_dbus_in(void) +static void z80_dbus_set_in(void) { DDR_DB = 0; P_DB = 0; } -static void z80_setup_dbus_out(void) +static void z80_dbus_set_out(void) { DDR_DB = 0xff; } @@ -209,20 +288,6 @@ static void z80_reset_pulse(void) Z80_O_RST = 1; } -static -void z80_setup_clock(void) -{ - /* ZCLK: Output and low */ - DDR_ZCLK |= _BV(ZCLK); - Z80_O_ZCLK = 0; - - /* Timer1: CTC: Toggle OC1C on compare match */ - PRR0 &= ~_BV(PRTIM1); - OCR1A = 0; - OCR1C = 0; - TCCR1A = (0b01 << COM1C0) | (0b00 << WGM10); - TCCR1B = (0b01 << WGM12) | (0b001 << CS10); -} void z80_setup_bus(void) { @@ -244,8 +309,8 @@ void z80_setup_bus(void) DDR_IOCS1 &= ~_BV(IOCS1); P_IOCS1 &= ~_BV(IOCS1); - z80_setup_addrbus_tristate(); - z80_setup_dbus_in(); + z80_addrbus_set_tristate(); + z80_dbus_set_in(); zstate = RESET; } @@ -259,8 +324,8 @@ zstate_t z80_bus_state(void) static void z80_busreq_hpulse(void) { - z80_setup_dbus_in(); - z80_setup_addrbus_tristate(); + z80_dbus_set_in(); + z80_addrbus_set_tristate(); ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { Z80_O_BUSREQ = 1; @@ -271,7 +336,7 @@ static void z80_busreq_hpulse(void) if (zstate & ZST_ACQUIRED) { while(Z80_I_BUSACK == 1) ; - z80_setup_addrbus_active(); + z80_addrbus_set_active(); } } @@ -310,8 +375,8 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd) switch (cmd) { case Reset: - z80_setup_dbus_in(); - z80_setup_addrbus_tristate(); + z80_dbus_set_in(); + z80_addrbus_set_tristate(); Z80_O_RST = 0; Z80_O_BUSREQ = 1; zstate = RESET; @@ -324,7 +389,7 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd) Z80_O_RST = 1; while(Z80_I_BUSACK == 1) ; - z80_setup_addrbus_active(); + z80_addrbus_set_active(); zstate = RESET_AQRD; break; @@ -332,7 +397,7 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd) Z80_O_BUSREQ = 0; while(Z80_I_BUSACK == 1) ; - z80_setup_addrbus_active(); + z80_addrbus_set_active(); zstate = RUNNING_AQRD; break; @@ -344,15 +409,15 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd) case Release: switch (zstate) { case RESET_AQRD: - z80_setup_dbus_in(); - z80_setup_addrbus_tristate(); + z80_dbus_set_in(); + z80_addrbus_set_tristate(); Z80_O_RST = 0; Z80_O_BUSREQ = 1; zstate = RESET; break; case RUNNING_AQRD: - z80_setup_dbus_in(); - z80_setup_addrbus_tristate(); + z80_dbus_set_in(); + z80_addrbus_set_tristate(); Z80_O_BUSREQ = 1; zstate = RUNNING; break; @@ -369,10 +434,10 @@ zstate_t z80_bus_cmd(bus_cmd_t cmd) break; case RESET_AQRD: - z80_setup_dbus_in(); - z80_setup_addrbus_tristate(); + z80_dbus_set_in(); + z80_addrbus_set_tristate(); z80_reset_pulse(); - z80_setup_addrbus_active(); + z80_addrbus_set_active(); zstate = RUNNING_AQRD; break; default: @@ -421,7 +486,7 @@ void z80_write(uint32_t addr, uint8_t data) { z80_setaddress(addr); Z80_O_MREQ = 0; - z80_setup_dbus_out(); + z80_dbus_set_out(); P_DB = data; P_DB = data; Z80_O_WR = 0; @@ -436,7 +501,7 @@ uint8_t z80_read(uint32_t addr) z80_setaddress(addr); Z80_O_MREQ = 0; - z80_setup_dbus_in(); + z80_dbus_set_in(); Z80_O_RD = 0; Z80_O_RD = 0; Z80_O_RD = 0; @@ -450,7 +515,7 @@ uint8_t z80_read(uint32_t addr) void z80_memset(uint32_t addr, uint8_t data, uint32_t length) { - z80_setup_dbus_out(); + z80_dbus_set_out(); Z80_O_MREQ = 0; while(length--) { z80_setaddress(addr++); @@ -467,7 +532,7 @@ void z80_write_block(const __flash uint8_t *src, uint32_t dest, uint32_t length) { uint8_t data; - z80_setup_dbus_out(); + z80_dbus_set_out(); Z80_O_MREQ = 0; while(length--) { z80_setaddress(dest++); diff --git a/include/z80-if.h b/include/z80-if.h index b02fe23..5153f37 100644 --- a/include/z80-if.h +++ b/include/z80-if.h @@ -2,14 +2,14 @@ #define ZST_ACQUIRED 0x01 #define ZST_RUNNING 0x02 -typedef enum { +typedef enum { RESET = 0x00, RESET_AQRD = ZST_ACQUIRED, RUNNING = ZST_RUNNING, RUNNING_AQRD = ZST_RUNNING | ZST_ACQUIRED, } zstate_t; -typedef enum { +typedef enum { Reset, Request, Release, @@ -26,6 +26,9 @@ void z80_setup_bus(void); int z80_stat_reset(void); //void z80_busreq(level_t level); int z80_stat_halt(void); +uint32_t z80_clock_get(void); +int z80_clock_set(unsigned long freq); + void z80_write(uint32_t addr, uint8_t data); uint8_t z80_read(uint32_t addr); -- cgit v1.2.3