2015-06-07 10:19:33 +00:00
|
|
|
#include <stdio.h>
|
2015-06-20 15:41:40 +00:00
|
|
|
#include <stdlib.h>
|
2015-06-07 10:19:33 +00:00
|
|
|
#include <string.h>
|
2015-06-11 17:23:47 +00:00
|
|
|
#include <ctype.h>
|
2015-06-07 10:19:33 +00:00
|
|
|
#include <avr/pgmspace.h>
|
|
|
|
|
|
|
|
#include "hd44780.h"
|
|
|
|
#include "status.h"
|
|
|
|
|
2015-06-16 17:41:46 +00:00
|
|
|
#ifdef EMBEDDED_6502
|
2015-06-20 17:18:05 +00:00
|
|
|
|
2015-06-20 21:36:10 +00:00
|
|
|
unsigned int disMem(unsigned int addr);
|
|
|
|
|
2015-06-18 12:14:10 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
IMP, IMPA, MARK2, BRA, IMM, ZP, ZPX, ZPY, INDX, INDY, IND, MARK3, ABS, ABSX, ABSY, IND16, IND1X
|
|
|
|
};
|
|
|
|
|
2015-06-20 17:18:05 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
I_ADC,
|
|
|
|
I_AND,
|
|
|
|
I_ASL,
|
|
|
|
I_BCC,
|
|
|
|
I_BCS,
|
|
|
|
I_BEQ,
|
|
|
|
I_BIT,
|
|
|
|
I_BMI,
|
|
|
|
I_BNE,
|
|
|
|
I_BPL,
|
|
|
|
I_BRA,
|
|
|
|
I_BRK,
|
|
|
|
I_BVC,
|
|
|
|
I_BVS,
|
|
|
|
I_CLC,
|
|
|
|
I_CLD,
|
|
|
|
I_CLI,
|
|
|
|
I_CLV,
|
|
|
|
I_CMP,
|
|
|
|
I_CPX,
|
|
|
|
I_CPY,
|
|
|
|
I_DEC,
|
|
|
|
I_DEX,
|
|
|
|
I_DEY,
|
|
|
|
I_EOR,
|
|
|
|
I_INC,
|
|
|
|
I_INX,
|
|
|
|
I_INY,
|
|
|
|
I_JMP,
|
|
|
|
I_JSR,
|
|
|
|
I_LDA,
|
|
|
|
I_LDX,
|
|
|
|
I_LDY,
|
|
|
|
I_LSR,
|
|
|
|
I_NOP,
|
|
|
|
I_ORA,
|
|
|
|
I_PHA,
|
|
|
|
I_PHP,
|
|
|
|
I_PHX,
|
|
|
|
I_PHY,
|
|
|
|
I_PLA,
|
|
|
|
I_PLP,
|
|
|
|
I_PLX,
|
|
|
|
I_PLY,
|
|
|
|
I_ROL,
|
|
|
|
I_ROR,
|
|
|
|
I_RTI,
|
|
|
|
I_RTS,
|
|
|
|
I_SBC,
|
|
|
|
I_SEC,
|
|
|
|
I_SED,
|
|
|
|
I_SEI,
|
|
|
|
I_STA,
|
|
|
|
I_STP,
|
|
|
|
I_STX,
|
|
|
|
I_STY,
|
|
|
|
I_STZ,
|
|
|
|
I_TAX,
|
|
|
|
I_TAY,
|
|
|
|
I_TRB,
|
|
|
|
I_TSB,
|
|
|
|
I_TSX,
|
|
|
|
I_TXA,
|
|
|
|
I_TXS,
|
|
|
|
I_TYA,
|
|
|
|
I_WAI,
|
|
|
|
I_XXX
|
|
|
|
};
|
|
|
|
|
|
|
|
char *opStrings[67] = {
|
|
|
|
"ADC",
|
|
|
|
"AND",
|
|
|
|
"ASL",
|
|
|
|
"BCC",
|
|
|
|
"BCS",
|
|
|
|
"BEQ",
|
|
|
|
"BIT",
|
|
|
|
"BMI",
|
|
|
|
"BNE",
|
|
|
|
"BPL",
|
|
|
|
"BRA",
|
|
|
|
"BRK",
|
|
|
|
"BVC",
|
|
|
|
"BVS",
|
|
|
|
"CLC",
|
|
|
|
"CLD",
|
|
|
|
"CLI",
|
|
|
|
"CLV",
|
|
|
|
"CMP",
|
|
|
|
"CPX",
|
|
|
|
"CPY",
|
|
|
|
"DEC",
|
|
|
|
"DEX",
|
|
|
|
"DEY",
|
|
|
|
"EOR",
|
|
|
|
"INC",
|
|
|
|
"INX",
|
|
|
|
"INY",
|
|
|
|
"JMP",
|
|
|
|
"JSR",
|
|
|
|
"LDA",
|
|
|
|
"LDX",
|
|
|
|
"LDY",
|
|
|
|
"LSR",
|
|
|
|
"NOP",
|
|
|
|
"ORA",
|
|
|
|
"PHA",
|
|
|
|
"PHP",
|
|
|
|
"PHX",
|
|
|
|
"PHY",
|
|
|
|
"PLA",
|
|
|
|
"PLP",
|
|
|
|
"PLX",
|
|
|
|
"PLY",
|
|
|
|
"ROL",
|
|
|
|
"ROR",
|
|
|
|
"RTI",
|
|
|
|
"RTS",
|
|
|
|
"SBC",
|
|
|
|
"SEC",
|
|
|
|
"SED",
|
|
|
|
"SEI",
|
|
|
|
"STA",
|
|
|
|
"STP",
|
|
|
|
"STX",
|
|
|
|
"STY",
|
|
|
|
"STZ",
|
|
|
|
"TAX",
|
|
|
|
"TAY",
|
|
|
|
"TRB",
|
|
|
|
"TSB",
|
|
|
|
"TSX",
|
|
|
|
"TXA",
|
|
|
|
"TXS",
|
|
|
|
"TYA",
|
|
|
|
"WAI",
|
|
|
|
"---"
|
|
|
|
};
|
2015-06-20 15:41:40 +00:00
|
|
|
|
2015-06-20 17:18:05 +00:00
|
|
|
unsigned char dopname[256] =
|
2015-06-18 12:14:10 +00:00
|
|
|
{
|
2015-06-20 17:18:05 +00:00
|
|
|
/*00*/ I_BRK, I_ORA, I_XXX, I_XXX, I_TSB, I_ORA, I_ASL, I_XXX, I_PHP, I_ORA, I_ASL, I_XXX, I_TSB, I_ORA, I_ASL, I_XXX,
|
|
|
|
/*10*/ I_BPL, I_ORA, I_ORA, I_XXX, I_TRB, I_ORA, I_ASL, I_XXX, I_CLC, I_ORA, I_INC, I_XXX, I_TRB, I_ORA, I_ASL, I_XXX,
|
|
|
|
/*20*/ I_JSR, I_AND, I_XXX, I_XXX, I_BIT, I_AND, I_ROL, I_XXX, I_PLP, I_AND, I_ROL, I_XXX, I_BIT, I_AND, I_ROL, I_XXX,
|
|
|
|
/*30*/ I_BMI, I_AND, I_AND, I_XXX, I_BIT, I_AND, I_ROL, I_XXX, I_SEC, I_AND, I_DEC, I_XXX, I_BIT, I_AND, I_ROL, I_XXX,
|
|
|
|
/*40*/ I_RTI, I_EOR, I_XXX, I_XXX, I_XXX, I_EOR, I_LSR, I_XXX, I_PHA, I_EOR, I_LSR, I_XXX, I_JMP, I_EOR, I_LSR, I_XXX,
|
|
|
|
/*50*/ I_BVC, I_EOR, I_EOR, I_XXX, I_XXX, I_EOR, I_LSR, I_XXX, I_CLI, I_EOR, I_PHY, I_XXX, I_XXX, I_EOR, I_LSR, I_XXX,
|
|
|
|
/*60*/ I_RTS, I_ADC, I_XXX, I_XXX, I_STZ, I_ADC, I_ROR, I_XXX, I_PLA, I_ADC, I_ROR, I_XXX, I_JMP, I_ADC, I_ROR, I_XXX,
|
|
|
|
/*70*/ I_BVS, I_ADC, I_ADC, I_XXX, I_STZ, I_ADC, I_ROR, I_XXX, I_SEI, I_ADC, I_PLY, I_XXX, I_JMP, I_ADC, I_ROR, I_XXX,
|
|
|
|
/*80*/ I_BRA, I_STA, I_XXX, I_XXX, I_STY, I_STA, I_STX, I_XXX, I_DEY, I_BIT, I_TXA, I_XXX, I_STY, I_STA, I_STX, I_XXX,
|
|
|
|
/*90*/ I_BCC, I_STA, I_STA, I_XXX, I_STY, I_STA, I_STX, I_XXX, I_TYA, I_STA, I_TXS, I_XXX, I_STZ, I_STA, I_STZ, I_XXX,
|
|
|
|
/*A0*/ I_LDY, I_LDA, I_LDX, I_XXX, I_LDY, I_LDA, I_LDX, I_XXX, I_TAY, I_LDA, I_TAX, I_XXX, I_LDY, I_LDA, I_LDX, I_XXX,
|
|
|
|
/*B0*/ I_BCS, I_LDA, I_LDA, I_XXX, I_LDY, I_LDA, I_LDX, I_XXX, I_CLV, I_LDA, I_TSX, I_XXX, I_LDY, I_LDA, I_LDX, I_XXX,
|
|
|
|
/*C0*/ I_CPY, I_CMP, I_XXX, I_XXX, I_CPY, I_CMP, I_DEC, I_XXX, I_INY, I_CMP, I_DEX, I_WAI, I_CPY, I_CMP, I_DEC, I_XXX,
|
|
|
|
/*D0*/ I_BNE, I_CMP, I_CMP, I_XXX, I_XXX, I_CMP, I_DEC, I_XXX, I_CLD, I_CMP, I_PHX, I_STP, I_XXX, I_CMP, I_DEC, I_XXX,
|
|
|
|
/*E0*/ I_CPX, I_SBC, I_XXX, I_XXX, I_CPX, I_SBC, I_INC, I_XXX, I_INX, I_SBC, I_NOP, I_XXX, I_CPX, I_SBC, I_INC, I_XXX,
|
|
|
|
/*F0*/ I_BEQ, I_SBC, I_SBC, I_XXX, I_XXX, I_SBC, I_INC, I_XXX, I_SED, I_SBC, I_PLX, I_XXX, I_XXX, I_SBC, I_INC, I_XXX
|
2015-06-18 12:14:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
unsigned char dopaddr[256] =
|
|
|
|
{
|
|
|
|
/*00*/ IMP, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMPA, IMP, ABS, ABS, ABS, IMP,
|
|
|
|
/*10*/ BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMPA, IMP, ABS, ABSX, ABSX, IMP,
|
|
|
|
/*20*/ ABS, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMPA, IMP, ABS, ABS, ABS, IMP,
|
|
|
|
/*30*/ BRA, INDY, IND, IMP, ZPX, ZPX, ZPX, IMP, IMP, ABSY, IMPA, IMP, ABSX, ABSX, ABSX, IMP,
|
|
|
|
/*40*/ IMP, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMPA, IMP, ABS, ABS, ABS, IMP,
|
|
|
|
/*50*/ BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP,
|
|
|
|
/*60*/ IMP, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMPA, IMP, IND16, ABS, ABS, IMP,
|
|
|
|
/*70*/ BRA, INDY, IND, IMP, ZPX, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, IND1X, ABSX, ABSX, IMP,
|
|
|
|
/*80*/ BRA, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP,
|
|
|
|
/*90*/ BRA, INDY, IND, IMP, ZPX, ZPX, ZPY, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP,
|
|
|
|
/*A0*/ IMM, INDX, IMM, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP,
|
|
|
|
/*B0*/ BRA, INDY, IND, IMP, ZPX, ZPX, ZPY, IMP, IMP, ABSY, IMP, IMP, ABSX, ABSX, ABSY, IMP,
|
|
|
|
/*C0*/ IMM, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP,
|
|
|
|
/*D0*/ BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP,
|
|
|
|
/*E0*/ IMM, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP,
|
2015-06-20 17:18:05 +00:00
|
|
|
/*F0*/ BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP
|
2015-06-18 12:14:10 +00:00
|
|
|
};
|
2015-06-16 17:41:46 +00:00
|
|
|
#endif
|
2015-06-07 16:58:14 +00:00
|
|
|
|
2015-06-20 15:41:40 +00:00
|
|
|
#define CRC_POLY 0x002d
|
|
|
|
|
2015-06-16 17:41:46 +00:00
|
|
|
#define CTRL_PORT PORTB
|
|
|
|
#define CTRL_DDR DDRB
|
|
|
|
#define CTRL_DIN PINB
|
2015-06-16 10:57:32 +00:00
|
|
|
|
2015-06-16 17:41:46 +00:00
|
|
|
#define MUXSEL_PORT PORTD
|
2015-06-10 14:49:14 +00:00
|
|
|
|
2015-06-16 17:41:46 +00:00
|
|
|
#define STATUS_PORT PORTD
|
|
|
|
#define STATUS_DDR DDRD
|
|
|
|
#define STATUS_DIN PIND
|
2015-06-10 14:49:14 +00:00
|
|
|
|
2015-06-16 17:41:46 +00:00
|
|
|
#define MUX_PORT PORTE
|
|
|
|
#define MUX_DDR DDRE
|
|
|
|
#define MUX_DIN PINE
|
2015-06-10 14:49:14 +00:00
|
|
|
|
2015-06-20 11:30:18 +00:00
|
|
|
// Hardware registers
|
2015-06-16 17:41:46 +00:00
|
|
|
#define OFFSET_IAL 0
|
|
|
|
#define OFFSET_IAH 1
|
2015-06-20 11:30:18 +00:00
|
|
|
#define OFFSET_DATA 2
|
|
|
|
#define OFFSET_CNTH 3
|
|
|
|
#define OFFSET_CNTL 4
|
|
|
|
#define OFFSET_CNTM 5
|
|
|
|
|
|
|
|
// Hardware fifo
|
|
|
|
#define OFFSET_BW_IAL 6
|
|
|
|
#define OFFSET_BW_IAH 7
|
|
|
|
#define OFFSET_BW_BAL 8
|
|
|
|
#define OFFSET_BW_BAH 9
|
|
|
|
#define OFFSET_BW_BD 10
|
|
|
|
#define OFFSET_BW_M 11
|
|
|
|
#define OFFSET_BW_CNTL 12
|
|
|
|
#define OFFSET_BW_CNTM 13
|
|
|
|
#define OFFSET_BW_CNTH 14
|
|
|
|
|
|
|
|
// Processor registers
|
|
|
|
#define OFFSET_REG_A 16
|
|
|
|
#define OFFSET_REG_X 17
|
|
|
|
#define OFFSET_REG_Y 18
|
|
|
|
#define OFFSET_REG_P 19
|
|
|
|
#define OFFSET_REG_SPL 20
|
|
|
|
#define OFFSET_REG_SPH 21
|
|
|
|
#define OFFSET_REG_PCL 22
|
|
|
|
#define OFFSET_REG_PCH 23
|
2015-06-16 10:57:32 +00:00
|
|
|
|
2015-06-10 14:49:14 +00:00
|
|
|
// Commands
|
|
|
|
// 000x Enable/Disable single strpping
|
|
|
|
// 001x Enable/Disable breakpoints / watches
|
|
|
|
// 010x Load register
|
|
|
|
// 011x Reset
|
|
|
|
// 1000 Singe Step
|
|
|
|
|
|
|
|
#define CMD_SINGLE_ENABLE 0x00
|
|
|
|
#define CMD_BRKPT_ENABLE 0x02
|
2015-06-16 17:41:46 +00:00
|
|
|
#define CMD_LOAD_BRKPT 0x04
|
2015-06-10 14:49:14 +00:00
|
|
|
#define CMD_RESET 0x06
|
|
|
|
#define CMD_STEP 0x08
|
2015-06-10 21:31:07 +00:00
|
|
|
#define CMD_WATCH_READ 0x09
|
2015-06-11 21:01:31 +00:00
|
|
|
#define CMD_FIFO_RST 0x0A
|
2015-06-16 17:41:46 +00:00
|
|
|
#define CMD_LOAD_MEM 0x0C
|
2015-06-22 17:11:11 +00:00
|
|
|
#define CMD_RD_MEM 0x10
|
|
|
|
#define CMD_RD_MEM_INC 0x11
|
|
|
|
#define CMD_WR_MEM 0x12
|
|
|
|
#define CMD_WR_MEM_INC 0x13
|
2015-06-10 14:49:14 +00:00
|
|
|
|
|
|
|
// Control bits
|
2015-06-22 17:11:11 +00:00
|
|
|
#define CMD_MASK 0x3F
|
|
|
|
#define CMD_EDGE 0x20
|
2015-06-20 11:30:18 +00:00
|
|
|
#define MUXSEL_MASK 0x1F
|
2015-06-16 10:57:32 +00:00
|
|
|
#define MUXSEL_BIT 0
|
2015-06-10 14:49:14 +00:00
|
|
|
|
|
|
|
// Status bits
|
2015-06-10 21:31:07 +00:00
|
|
|
#define INTERRUPTED_MASK 0x40
|
2015-06-11 20:39:07 +00:00
|
|
|
#define BW_ACTIVE_MASK 0x80
|
2015-06-07 16:58:14 +00:00
|
|
|
|
2015-06-10 10:55:39 +00:00
|
|
|
// Breakpoint Modes
|
2015-06-20 11:30:18 +00:00
|
|
|
#define BRKPT_EXEC 0
|
2015-06-10 21:31:07 +00:00
|
|
|
#define BRKPT_READ 1
|
|
|
|
#define BRKPT_WRITE 2
|
2015-06-20 11:30:18 +00:00
|
|
|
#define WATCH_EXEC 3
|
2015-06-10 21:31:07 +00:00
|
|
|
#define WATCH_READ 4
|
|
|
|
#define WATCH_WRITE 5
|
|
|
|
#define UNDEFINED 6
|
|
|
|
|
2015-06-20 11:30:18 +00:00
|
|
|
#define B_MASK ((1<<BRKPT_READ) | (1<<BRKPT_WRITE) | (1<<BRKPT_EXEC))
|
|
|
|
#define W_MASK ((1<<WATCH_READ) | (1<<WATCH_WRITE) | (1<<WATCH_EXEC))
|
2015-06-19 15:59:15 +00:00
|
|
|
#define B_MEM_MASK ((1<<BRKPT_READ) | (1<<BRKPT_WRITE))
|
2015-06-20 11:30:18 +00:00
|
|
|
#define W_MEM_MASK ((1<<BRKPT_WRITE) | (1<<WATCH_WRITE))
|
2015-06-10 21:31:07 +00:00
|
|
|
#define BW_MEM_MASK ((1<<BRKPT_READ) | (1<<BRKPT_WRITE) | (1<<WATCH_READ) | (1<<WATCH_WRITE))
|
|
|
|
|
2015-06-20 15:41:40 +00:00
|
|
|
char *testNames[6] = {
|
|
|
|
"Fixed",
|
|
|
|
"Checkerboard",
|
|
|
|
"Inverse checkerboard",
|
|
|
|
"Address pattern",
|
|
|
|
"Inverse address pattern",
|
|
|
|
"Random"
|
|
|
|
};
|
|
|
|
|
2015-06-10 21:31:07 +00:00
|
|
|
char *modeStrings[7] = {
|
2015-06-20 11:30:18 +00:00
|
|
|
"Ex Breakpoint",
|
|
|
|
"Rn Breakpoint",
|
|
|
|
"Wr Breakpoint",
|
|
|
|
"Ex watch",
|
|
|
|
"Rd watch",
|
|
|
|
"Wr watch",
|
2015-06-13 12:39:39 +00:00
|
|
|
"Undefined"
|
2015-06-10 10:55:39 +00:00
|
|
|
};
|
|
|
|
|
2015-06-13 12:39:39 +00:00
|
|
|
#define NUM_TRIGGERS 16
|
|
|
|
#define TRIGGER_ALWAYS 15
|
|
|
|
|
|
|
|
char *triggerStrings[NUM_TRIGGERS] = {
|
|
|
|
"Never",
|
|
|
|
"~T0 and ~T1",
|
|
|
|
"T0 and ~T1",
|
|
|
|
"~T1",
|
|
|
|
"~T0 and T1",
|
|
|
|
"~T0",
|
|
|
|
"T0 xor T1",
|
|
|
|
"~T0 or ~T1",
|
|
|
|
"T0 and T1",
|
|
|
|
"T0 xnor T1",
|
|
|
|
"T0",
|
|
|
|
"T0 or ~T1",
|
|
|
|
"T1",
|
|
|
|
"~T0 or T1",
|
|
|
|
"T0 or T1",
|
|
|
|
"Always",
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-06-22 17:11:11 +00:00
|
|
|
#define VERSION "0.37"
|
2015-06-07 10:19:33 +00:00
|
|
|
|
2015-06-16 10:57:32 +00:00
|
|
|
#ifdef EMBEDDED_6502
|
2015-06-20 15:41:40 +00:00
|
|
|
#define NUM_CMDS 27
|
2015-06-16 10:57:32 +00:00
|
|
|
#else
|
2015-06-13 12:39:39 +00:00
|
|
|
#define NUM_CMDS 19
|
2015-06-16 10:57:32 +00:00
|
|
|
#endif
|
|
|
|
|
2015-06-11 17:23:47 +00:00
|
|
|
#define MAXBKPTS 8
|
2015-06-07 10:19:33 +00:00
|
|
|
|
|
|
|
int numbkpts = 0;
|
|
|
|
|
|
|
|
long trace;
|
|
|
|
long instructions = 1;
|
|
|
|
|
2015-06-16 17:41:46 +00:00
|
|
|
unsigned int memAddr = 0;
|
|
|
|
|
2015-06-17 10:40:59 +00:00
|
|
|
char statusString[8] = "NV-BDIZC";
|
|
|
|
|
2015-06-07 10:19:33 +00:00
|
|
|
unsigned int breakpoints[MAXBKPTS] = {
|
2015-06-13 12:39:39 +00:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2015-06-07 10:19:33 +00:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2015-06-19 15:10:07 +00:00
|
|
|
unsigned int masks[MAXBKPTS] = {
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2015-06-10 10:55:39 +00:00
|
|
|
unsigned int modes[MAXBKPTS] = {
|
2015-06-13 12:39:39 +00:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2015-06-19 15:10:07 +00:00
|
|
|
int triggers[MAXBKPTS] = {
|
2015-06-13 12:39:39 +00:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2015-06-10 10:55:39 +00:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-06-13 12:39:39 +00:00
|
|
|
char *cmdStrings[NUM_CMDS] = {
|
2015-06-07 10:19:33 +00:00
|
|
|
"help",
|
2015-06-20 15:41:40 +00:00
|
|
|
"continue",
|
2015-06-16 10:57:32 +00:00
|
|
|
#ifdef EMBEDDED_6502
|
|
|
|
"regs",
|
2015-06-16 17:41:46 +00:00
|
|
|
"mem",
|
|
|
|
"dis",
|
2015-06-17 10:17:12 +00:00
|
|
|
"read",
|
2015-06-16 17:41:46 +00:00
|
|
|
"write",
|
2015-06-18 11:58:37 +00:00
|
|
|
"fill",
|
2015-06-20 15:41:40 +00:00
|
|
|
"crc",
|
|
|
|
"test",
|
2015-06-16 10:57:32 +00:00
|
|
|
#endif
|
2015-06-07 10:19:33 +00:00
|
|
|
"reset",
|
|
|
|
"step",
|
|
|
|
"trace",
|
|
|
|
"blist",
|
2015-06-10 10:55:39 +00:00
|
|
|
"breaki",
|
|
|
|
"breakr",
|
|
|
|
"breakw",
|
2015-06-10 21:31:07 +00:00
|
|
|
"watchi",
|
|
|
|
"watchr",
|
|
|
|
"watchw",
|
2015-06-10 11:53:53 +00:00
|
|
|
"bcleari",
|
|
|
|
"bclearr",
|
|
|
|
"bclearw",
|
2015-06-10 21:31:07 +00:00
|
|
|
"wcleari",
|
|
|
|
"wclearr",
|
|
|
|
"wclearw",
|
2015-06-20 15:41:40 +00:00
|
|
|
"trigger"
|
2015-06-07 10:19:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define Delay_us(__us) \
|
|
|
|
if((unsigned long) (F_CPU/1000000.0 * __us) != F_CPU/1000000.0 * __us)\
|
|
|
|
__builtin_avr_delay_cycles((unsigned long) ( F_CPU/1000000.0 * __us)+1);\
|
|
|
|
else __builtin_avr_delay_cycles((unsigned long) ( F_CPU/1000000.0 * __us))
|
|
|
|
|
|
|
|
#define Delay_ms(__ms) \
|
|
|
|
if((unsigned long) (F_CPU/1000.0 * __ms) != F_CPU/1000.0 * __ms)\
|
|
|
|
__builtin_avr_delay_cycles((unsigned long) ( F_CPU/1000.0 * __ms)+1);\
|
|
|
|
else __builtin_avr_delay_cycles((unsigned long) ( F_CPU/1000.0 * __ms))
|
|
|
|
|
|
|
|
char message[32];
|
|
|
|
char command[32];
|
|
|
|
|
|
|
|
void readCmd(char *cmd) {
|
|
|
|
char c;
|
|
|
|
int i = 0;
|
|
|
|
log0(">> ");
|
|
|
|
while (1) {
|
|
|
|
c = Serial_RxByte0();
|
|
|
|
if (c == 8) {
|
|
|
|
// Handle backspace/delete
|
|
|
|
if (i > 0) {
|
|
|
|
i--;
|
|
|
|
Serial_TxByte0(c);
|
|
|
|
Serial_TxByte0(32);
|
|
|
|
Serial_TxByte0(c);
|
|
|
|
}
|
|
|
|
} else if (c == 13) {
|
|
|
|
// Handle return
|
|
|
|
if (i == 0) {
|
|
|
|
while (cmd[i]) {
|
|
|
|
Serial_TxByte0(cmd[i++]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cmd[i] = 0;
|
|
|
|
}
|
|
|
|
Serial_TxByte0(10);
|
|
|
|
Serial_TxByte0(13);
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
// Handle any other character
|
|
|
|
Serial_TxByte0(c);
|
|
|
|
cmd[i] = c;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-10 14:49:14 +00:00
|
|
|
void hwCmd(unsigned int cmd, unsigned int param) {
|
|
|
|
cmd |= param;
|
|
|
|
CTRL_PORT &= ~CMD_MASK;
|
|
|
|
CTRL_PORT |= cmd;
|
|
|
|
Delay_us(2);
|
|
|
|
CTRL_PORT |= CMD_EDGE;
|
|
|
|
Delay_us(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int hwRead8(unsigned int offset) {
|
2015-06-16 10:57:32 +00:00
|
|
|
MUXSEL_PORT &= ~MUXSEL_MASK;
|
|
|
|
MUXSEL_PORT |= offset << MUXSEL_BIT;
|
2015-06-10 14:49:14 +00:00
|
|
|
Delay_us(1);
|
|
|
|
return MUX_DIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int hwRead16(unsigned int offset) {
|
|
|
|
unsigned int lsb;
|
2015-06-16 10:57:32 +00:00
|
|
|
MUXSEL_PORT &= ~MUXSEL_MASK;
|
|
|
|
MUXSEL_PORT |= offset << MUXSEL_BIT;
|
2015-06-10 14:49:14 +00:00
|
|
|
Delay_us(1);
|
|
|
|
lsb = MUX_DIN;
|
2015-06-16 10:57:32 +00:00
|
|
|
MUXSEL_PORT |= 1 << MUXSEL_BIT;
|
2015-06-10 14:49:14 +00:00
|
|
|
Delay_us(1);
|
|
|
|
return (MUX_DIN << 8) | lsb;
|
|
|
|
}
|
|
|
|
|
2015-06-20 15:41:40 +00:00
|
|
|
void setSingle(int single) {
|
2015-06-10 14:49:14 +00:00
|
|
|
hwCmd(CMD_SINGLE_ENABLE, single ? 1 : 0);
|
2015-06-07 10:19:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setTrace(long i) {
|
|
|
|
trace = i;
|
|
|
|
if (trace) {
|
2015-06-07 16:58:14 +00:00
|
|
|
log0("Tracing every %ld instructions while single stepping\n", trace);
|
2015-06-07 10:19:33 +00:00
|
|
|
} else {
|
|
|
|
log0("Tracing disabled\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-07 16:58:14 +00:00
|
|
|
void version() {
|
|
|
|
log0("Atom Bus Monitor version %s\n", VERSION);
|
|
|
|
log0("Compiled at %s on %s\n",__TIME__,__DATE__);
|
|
|
|
}
|
2015-06-07 10:19:33 +00:00
|
|
|
|
2015-06-10 10:55:39 +00:00
|
|
|
|
2015-06-16 10:57:32 +00:00
|
|
|
#ifdef LCD
|
2015-06-10 15:35:38 +00:00
|
|
|
void lcdAddr(unsigned int addr) {
|
|
|
|
int i;
|
|
|
|
int nibble;
|
|
|
|
lcd_goto(6);
|
|
|
|
// Avoid using sprintf, as it adds quite a lot of code
|
|
|
|
for (i = 3; i >= 0; i--) {
|
|
|
|
nibble = addr >> (i * 4);
|
|
|
|
nibble &= 0x0F;
|
|
|
|
nibble += '0';
|
|
|
|
if (nibble > '9') {
|
|
|
|
nibble += 'A' - '9' - 1;
|
|
|
|
}
|
|
|
|
lcd_putc(nibble);
|
|
|
|
}
|
|
|
|
}
|
2015-06-16 10:57:32 +00:00
|
|
|
#endif
|
|
|
|
|
2015-06-13 12:39:39 +00:00
|
|
|
int lookupBreakpoint(char *params) {
|
|
|
|
int i;
|
2015-06-16 17:41:46 +00:00
|
|
|
int n = -1;
|
2015-06-13 12:39:39 +00:00
|
|
|
sscanf(params, "%x", &n);
|
|
|
|
// First, look assume n is an address, and try to map to an index
|
|
|
|
for (i = 0; i < numbkpts; i++) {
|
|
|
|
if (breakpoints[i] == n) {
|
|
|
|
n = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (n < numbkpts) {
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
log0("Breakpoint/watch not set at %04X\n", n);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-20 21:36:10 +00:00
|
|
|
void logCycleCount(int offsetLow, int offsetHigh) {
|
|
|
|
unsigned long count = (((unsigned long) hwRead8(offsetHigh)) << 16) | hwRead16(offsetLow);
|
|
|
|
unsigned long countSecs = count / 1000000;
|
|
|
|
unsigned long countMicros = count % 1000000;
|
|
|
|
log0("%02ld.%06ld: ", countSecs, countMicros);
|
|
|
|
}
|
|
|
|
|
|
|
|
void logMode(unsigned int mode) {
|
|
|
|
int i;
|
|
|
|
int first = 1;
|
|
|
|
for (i = 0; i < UNDEFINED; i++) {
|
|
|
|
if (mode & 1) {
|
|
|
|
if (first) {
|
|
|
|
log0("%s", modeStrings[i]);
|
|
|
|
} else {
|
|
|
|
log0(", %c%s", tolower(*modeStrings[i]), modeStrings[i] + 1);
|
|
|
|
}
|
|
|
|
first = 0;
|
|
|
|
}
|
|
|
|
mode >>= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void logTrigger(int trigger) {
|
|
|
|
if (trigger >= 0 && trigger < NUM_TRIGGERS) {
|
|
|
|
log0("trigger: %s", triggerStrings[trigger]);
|
|
|
|
} else {
|
|
|
|
log0("trigger: ILLEGAL");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int logDetails() {
|
|
|
|
unsigned int i_addr = hwRead16(OFFSET_BW_IAL);
|
|
|
|
unsigned int b_addr = hwRead16(OFFSET_BW_BAL);
|
|
|
|
unsigned int b_data = hwRead8(OFFSET_BW_BD);
|
|
|
|
unsigned int mode = hwRead8(OFFSET_BW_M);
|
|
|
|
unsigned int watch = mode & 8;
|
|
|
|
|
|
|
|
|
|
|
|
// Convert from 4-bit compressed to 6 bit expanded mode representation
|
|
|
|
if (watch) {
|
|
|
|
mode = (mode & 7) << 3;
|
|
|
|
}
|
|
|
|
// Update the serial console
|
|
|
|
if (mode & W_MASK) {
|
|
|
|
logCycleCount(OFFSET_BW_CNTL, OFFSET_BW_CNTH);
|
|
|
|
}
|
|
|
|
logMode(mode);
|
|
|
|
log0(" hit at %04X", i_addr);
|
|
|
|
if (mode & BW_MEM_MASK) {
|
|
|
|
if (mode & W_MEM_MASK) {
|
|
|
|
log0(" writing");
|
|
|
|
} else {
|
|
|
|
log0(" reading");
|
|
|
|
}
|
|
|
|
log0(" %04X = %02X\n", b_addr, b_data);
|
|
|
|
if (mode & B_MASK) {
|
|
|
|
logCycleCount(OFFSET_BW_CNTL, OFFSET_BW_CNTH);
|
|
|
|
}
|
|
|
|
#ifdef EMBEDDED_6502
|
|
|
|
if (mode & B_MEM_MASK) {
|
|
|
|
// It's only safe to do this for brkpts, as it makes memory accesses
|
|
|
|
disMem(i_addr);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
log0("\n");
|
|
|
|
}
|
|
|
|
return watch;
|
|
|
|
}
|
|
|
|
|
2015-06-16 17:41:46 +00:00
|
|
|
#ifdef EMBEDDED_6502
|
2015-06-18 11:58:37 +00:00
|
|
|
void loadData(unsigned int data) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i <= 7; i++) {
|
|
|
|
hwCmd(CMD_LOAD_MEM, data & 1);
|
|
|
|
data >>= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void loadAddr(unsigned int addr) {
|
2015-06-16 17:41:46 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i <= 15; i++) {
|
|
|
|
hwCmd(CMD_LOAD_MEM, addr & 1);
|
|
|
|
addr >>= 1;
|
|
|
|
}
|
2015-06-18 11:58:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int readByte() {
|
2015-06-16 17:41:46 +00:00
|
|
|
hwCmd(CMD_RD_MEM, 0);
|
|
|
|
Delay_us(10);
|
|
|
|
return hwRead8(OFFSET_DATA);
|
|
|
|
}
|
|
|
|
|
2015-06-22 17:11:11 +00:00
|
|
|
unsigned int readByteInc() {
|
|
|
|
hwCmd(CMD_RD_MEM_INC, 0);
|
|
|
|
Delay_us(10);
|
|
|
|
return hwRead8(OFFSET_DATA);
|
2015-06-16 17:41:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-22 17:11:11 +00:00
|
|
|
void writeByte() {
|
|
|
|
hwCmd(CMD_WR_MEM, 0);
|
2015-06-18 11:58:37 +00:00
|
|
|
}
|
|
|
|
|
2015-06-22 17:11:11 +00:00
|
|
|
void writeByteInc() {
|
|
|
|
hwCmd(CMD_WR_MEM_INC, 0);
|
2015-06-18 11:58:37 +00:00
|
|
|
}
|
|
|
|
|
2015-06-18 12:14:10 +00:00
|
|
|
unsigned int disassemble(unsigned int addr)
|
|
|
|
{
|
|
|
|
unsigned int temp;
|
2015-06-22 17:11:11 +00:00
|
|
|
unsigned int op = readByteInc();
|
2015-06-18 12:14:10 +00:00
|
|
|
int mode = dopaddr[op];
|
2015-06-22 17:11:11 +00:00
|
|
|
unsigned int p1 = (mode > MARK2) ? readByteInc() : 0;
|
|
|
|
unsigned int p2 = (mode > MARK3) ? readByteInc() : 0;
|
2015-06-18 12:14:10 +00:00
|
|
|
|
2015-06-20 17:18:05 +00:00
|
|
|
log0("%04X : %s ", addr, opStrings[dopname[op]]);
|
2015-06-18 12:14:10 +00:00
|
|
|
switch (mode)
|
|
|
|
{
|
|
|
|
case IMP:
|
|
|
|
log0(" ");
|
|
|
|
break;
|
|
|
|
case IMPA:
|
|
|
|
log0("A ");
|
|
|
|
break;
|
|
|
|
case BRA:
|
|
|
|
temp = addr + 2 + (signed char)p1;
|
|
|
|
log0("%04X ", temp);
|
|
|
|
addr++;
|
|
|
|
break;
|
|
|
|
case IMM:
|
|
|
|
log0("#%02X ", p1);
|
|
|
|
addr++;
|
|
|
|
break;
|
|
|
|
case ZP:
|
|
|
|
log0("%02X ", p1);
|
|
|
|
addr++;
|
|
|
|
break;
|
|
|
|
case ZPX:
|
|
|
|
log0("%02X,X ", p1);
|
|
|
|
addr++;
|
|
|
|
break;
|
|
|
|
case ZPY:
|
|
|
|
log0("%02X,Y ", p1);
|
|
|
|
addr++;
|
|
|
|
break;
|
|
|
|
case IND:
|
|
|
|
log0("(%02X) ", p1);
|
|
|
|
addr++;
|
|
|
|
break;
|
|
|
|
case INDX:
|
|
|
|
log0("(%02X,X) ", p1);
|
|
|
|
addr++;
|
|
|
|
break;
|
|
|
|
case INDY:
|
|
|
|
log0("(%02X),Y ", p1);
|
|
|
|
addr++;
|
|
|
|
break;
|
|
|
|
case ABS:
|
|
|
|
log0("%02X%02X ", p2, p1);
|
|
|
|
addr += 2;
|
|
|
|
break;
|
|
|
|
case ABSX:
|
|
|
|
log0("%02X%02X,X ", p2, p1);
|
|
|
|
addr += 2;
|
|
|
|
break;
|
|
|
|
case ABSY:
|
|
|
|
log0("%02X%02X,Y ", p2, p1);
|
|
|
|
addr += 2;
|
|
|
|
break;
|
|
|
|
case IND16:
|
|
|
|
log0("(%02X%02X) ", p2, p1);
|
|
|
|
addr += 2;
|
|
|
|
break;
|
|
|
|
case IND1X:
|
|
|
|
log0("(%02X%02X,X)", p2, p1);
|
|
|
|
addr += 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
log0("\n");
|
|
|
|
addr++;
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
2015-06-16 17:41:46 +00:00
|
|
|
unsigned int disMem(unsigned int addr) {
|
2015-06-18 12:14:10 +00:00
|
|
|
loadAddr(addr);
|
|
|
|
return disassemble(addr);
|
2015-06-20 11:30:18 +00:00
|
|
|
|
2015-06-07 10:19:33 +00:00
|
|
|
}
|
2015-06-19 15:10:07 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
void logAddr() {
|
2015-06-16 17:41:46 +00:00
|
|
|
memAddr = hwRead16(OFFSET_IAL);
|
2015-06-10 15:35:38 +00:00
|
|
|
// Update the LCD display
|
2015-06-16 10:57:32 +00:00
|
|
|
#ifdef LCD
|
2015-06-16 17:41:46 +00:00
|
|
|
lcdAddr(memAddr);
|
2015-06-16 10:57:32 +00:00
|
|
|
#endif
|
2015-06-10 15:35:38 +00:00
|
|
|
// Update the serial console
|
2015-06-20 11:30:18 +00:00
|
|
|
logCycleCount(OFFSET_CNTL, OFFSET_CNTH);
|
2015-06-16 17:41:46 +00:00
|
|
|
#ifdef EMBEDDED_6502
|
|
|
|
//log0("%04X\n", i_addr);
|
|
|
|
disMem(memAddr);
|
|
|
|
#else
|
|
|
|
log0("%04X\n", memAddr);
|
|
|
|
#endif
|
|
|
|
return;
|
2015-06-10 15:35:38 +00:00
|
|
|
}
|
|
|
|
|
2015-06-19 15:10:07 +00:00
|
|
|
/*******************************************
|
|
|
|
* Commands
|
|
|
|
*******************************************/
|
|
|
|
|
|
|
|
void doCmdHelp(char *params) {
|
|
|
|
int i;
|
|
|
|
version();
|
|
|
|
log0("Commands:\n");
|
|
|
|
for (i = 0; i < NUM_CMDS; i++) {
|
|
|
|
log0(" %s\n", cmdStrings[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-07 10:19:33 +00:00
|
|
|
void doCmdStep(char *params) {
|
|
|
|
long i;
|
|
|
|
long j;
|
|
|
|
|
|
|
|
sscanf(params, "%ld", &instructions);
|
|
|
|
if (instructions <= 0) {
|
|
|
|
log0("Number of instuctions must be positive\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
log0("Stepping %ld instructions\n", instructions);
|
|
|
|
|
|
|
|
j = trace;
|
|
|
|
for (i = 1; i <= instructions; i++) {
|
|
|
|
// Step the 6502
|
2015-06-10 14:49:14 +00:00
|
|
|
hwCmd(CMD_STEP, 0);
|
2015-06-07 10:19:33 +00:00
|
|
|
if (i == instructions || (trace && (--j == 0))) {
|
2015-06-07 16:58:14 +00:00
|
|
|
Delay_us(10);
|
2015-06-19 15:10:07 +00:00
|
|
|
logAddr();
|
2015-06-07 10:19:33 +00:00
|
|
|
j = trace;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdReset(char *params) {
|
2015-06-07 10:45:34 +00:00
|
|
|
log0("Resetting 6502\n");
|
2015-06-10 14:49:14 +00:00
|
|
|
hwCmd(CMD_RESET, 1);
|
2015-06-20 15:41:40 +00:00
|
|
|
Delay_us(50);
|
|
|
|
hwCmd(CMD_STEP, 0);
|
|
|
|
Delay_us(50);
|
2015-06-10 14:49:14 +00:00
|
|
|
hwCmd(CMD_RESET, 0);
|
2015-06-07 10:19:33 +00:00
|
|
|
}
|
|
|
|
|
2015-06-16 10:57:32 +00:00
|
|
|
#ifdef EMBEDDED_6502
|
|
|
|
void doCmdRegs(char *params) {
|
2015-06-17 10:40:59 +00:00
|
|
|
int i;
|
|
|
|
log0("6502 Registers:\n");
|
|
|
|
log0(" A=%02X X=%02X Y=%02X SP=01%02X PC=%04X\n",
|
|
|
|
hwRead8(OFFSET_REG_A),
|
|
|
|
hwRead8(OFFSET_REG_X),
|
|
|
|
hwRead8(OFFSET_REG_Y),
|
|
|
|
hwRead8(OFFSET_REG_SPL),
|
|
|
|
hwRead16(OFFSET_REG_PCL));
|
|
|
|
unsigned int p = hwRead8(OFFSET_REG_P);
|
|
|
|
char *sp = statusString;
|
|
|
|
log0(" P=%02X ", p);
|
|
|
|
for (i = 0; i <= 7; i++) {
|
|
|
|
log0("%c", ((p & 128) ? (*sp) : '-'));
|
|
|
|
p <<= 1;
|
|
|
|
sp++;
|
|
|
|
}
|
|
|
|
log0("\n");
|
2015-06-16 10:57:32 +00:00
|
|
|
}
|
2015-06-16 17:41:46 +00:00
|
|
|
|
|
|
|
void doCmdMem(char *params) {
|
2015-06-17 10:40:59 +00:00
|
|
|
int i, j;
|
|
|
|
unsigned int row[16];
|
2015-06-18 11:58:37 +00:00
|
|
|
sscanf(params, "%x", &memAddr);
|
|
|
|
loadAddr(memAddr);
|
2015-06-17 10:40:59 +00:00
|
|
|
for (i = 0; i < 0x100; i+= 16) {
|
|
|
|
for (j = 0; j < 16; j++) {
|
2015-06-22 17:11:11 +00:00
|
|
|
row[j] = readByteInc();
|
2015-06-16 17:41:46 +00:00
|
|
|
}
|
2015-06-17 10:40:59 +00:00
|
|
|
log0("%04X ", memAddr + i);
|
|
|
|
for (j = 0; j < 16; j++) {
|
|
|
|
log0("%02X ", row[j]);
|
|
|
|
}
|
|
|
|
log0(" ");
|
|
|
|
for (j = 0; j < 16; j++) {
|
|
|
|
unsigned int c = row[j];
|
|
|
|
if (c < 32 || c > 126) {
|
|
|
|
c = '.';
|
|
|
|
}
|
|
|
|
log0("%c", c);
|
2015-06-16 17:41:46 +00:00
|
|
|
}
|
2015-06-17 10:40:59 +00:00
|
|
|
log0("\n");
|
2015-06-16 17:41:46 +00:00
|
|
|
}
|
|
|
|
memAddr += 0x100;
|
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdDis(char *params) {
|
|
|
|
int i;
|
|
|
|
sscanf(params, "%x", &memAddr);
|
2015-06-18 12:14:10 +00:00
|
|
|
loadAddr(memAddr);
|
2015-06-16 17:41:46 +00:00
|
|
|
for (i = 0; i < 10; i++) {
|
2015-06-18 12:14:10 +00:00
|
|
|
memAddr = disassemble(memAddr);
|
2015-06-16 17:41:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdWrite(char *params) {
|
|
|
|
unsigned int addr;
|
|
|
|
unsigned int data;
|
2015-06-22 17:11:11 +00:00
|
|
|
long count = 1;
|
|
|
|
sscanf(params, "%x %x %ld", &addr, &data, &count);
|
2015-06-16 17:41:46 +00:00
|
|
|
log0("Wr: %04X = %X\n", addr, data);
|
2015-06-22 17:11:11 +00:00
|
|
|
loadData(data);
|
|
|
|
loadAddr(addr);
|
|
|
|
while (count-- > 0) {
|
|
|
|
writeByte();
|
|
|
|
}
|
2015-06-16 17:41:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-17 10:17:12 +00:00
|
|
|
void doCmdRead(char *params) {
|
|
|
|
unsigned int addr;
|
|
|
|
unsigned int data;
|
2015-06-22 17:11:11 +00:00
|
|
|
unsigned int data2;
|
|
|
|
long count = 1;
|
|
|
|
sscanf(params, "%x %ld", &addr, &count);
|
|
|
|
loadAddr(addr);
|
|
|
|
data = readByte();
|
2015-06-17 10:17:12 +00:00
|
|
|
log0("Rd: %04X = %X\n", addr, data);
|
2015-06-22 17:11:11 +00:00
|
|
|
while (count-- > 1) {
|
|
|
|
data2 = readByte();
|
|
|
|
if (data2 != data) {
|
|
|
|
log0("Inconsistent Rd: %02X <> %02X\n", data2, data);
|
|
|
|
}
|
|
|
|
data = data2;
|
|
|
|
}
|
2015-06-17 10:17:12 +00:00
|
|
|
}
|
|
|
|
|
2015-06-18 11:58:37 +00:00
|
|
|
void doCmdFill(char *params) {
|
2015-06-20 15:41:40 +00:00
|
|
|
long i;
|
2015-06-18 11:58:37 +00:00
|
|
|
unsigned int start;
|
|
|
|
unsigned int end;
|
|
|
|
unsigned int data;
|
|
|
|
sscanf(params, "%x %x %x", &start, &end, &data);
|
|
|
|
log0("Wr: %04X to %04X = %X\n", start, end, data);
|
|
|
|
loadData(data);
|
|
|
|
loadAddr(start);
|
2015-06-20 15:41:40 +00:00
|
|
|
for (i = start; i <= end; i++) {
|
2015-06-22 17:11:11 +00:00
|
|
|
writeByteInc();
|
2015-06-18 11:58:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-20 15:41:40 +00:00
|
|
|
void doCmdCrc(char *params) {
|
|
|
|
long i;
|
|
|
|
int j;
|
|
|
|
unsigned int start;
|
|
|
|
unsigned int end;
|
|
|
|
unsigned int data;
|
|
|
|
unsigned long crc = 0;
|
|
|
|
sscanf(params, "%x %x", &start, &end);
|
|
|
|
loadAddr(start);
|
|
|
|
for (i = start; i <= end; i++) {
|
2015-06-22 17:11:11 +00:00
|
|
|
data = readByteInc();
|
2015-06-20 15:41:40 +00:00
|
|
|
for (j = 0; j < 8; j++) {
|
|
|
|
crc = crc << 1;
|
|
|
|
crc = crc | (data & 1);
|
|
|
|
data >>= 1;
|
|
|
|
if (crc & 0x10000)
|
|
|
|
crc = (crc ^ CRC_POLY) & 0xFFFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log0("crc: %04X\n", crc);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int getData(unsigned int addr, int data) {
|
|
|
|
if (data == -1) {
|
|
|
|
// checkerboard
|
|
|
|
return (addr & 1) ? 0x55 : 0xAA;
|
|
|
|
} else if (data == -2) {
|
|
|
|
// inverse checkerboard
|
|
|
|
return (addr & 1) ? 0xAA : 0x55;
|
|
|
|
} else if (data == -3) {
|
|
|
|
// address pattern
|
|
|
|
return (0xC3 ^ addr ^ (addr >> 8)) & 0xff;
|
|
|
|
} else if (data == -4) {
|
|
|
|
// address pattern
|
|
|
|
return (0x3C ^ addr ^ (addr >> 8)) & 0xff;
|
|
|
|
} else if (data < 0) {
|
|
|
|
// random data
|
|
|
|
return rand() & 0xff;
|
|
|
|
} else {
|
|
|
|
// fixed data
|
|
|
|
return data & 0xff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void test(unsigned int start, unsigned int end, int data) {
|
|
|
|
long i;
|
|
|
|
int name;
|
|
|
|
int actual;
|
|
|
|
int expected;
|
|
|
|
unsigned int fail = 0;
|
|
|
|
// Write
|
|
|
|
srand(data);
|
|
|
|
for (i = start; i <= end; i++) {
|
2015-06-22 17:11:11 +00:00
|
|
|
loadData(getData(i, data));
|
|
|
|
loadAddr(i);
|
|
|
|
writeByteInc();
|
2015-06-20 15:41:40 +00:00
|
|
|
}
|
|
|
|
// Read
|
|
|
|
srand(data);
|
|
|
|
loadAddr(start);
|
|
|
|
for (i = start; i <= end; i++) {
|
2015-06-22 17:11:11 +00:00
|
|
|
actual = readByteInc();
|
2015-06-20 15:41:40 +00:00
|
|
|
expected = getData(i, data);
|
|
|
|
if (expected != actual) {
|
2015-06-20 15:56:49 +00:00
|
|
|
log0("Fail at %04lX (Wrote: %02X, Read back %02X)\n", i, expected, actual);
|
2015-06-20 15:41:40 +00:00
|
|
|
fail++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
name = -data;
|
|
|
|
if (name < 0) {
|
|
|
|
name = 0;
|
|
|
|
}
|
|
|
|
if (name > 5) {
|
|
|
|
name = 5;
|
|
|
|
}
|
|
|
|
log0("Memory test: %s", testNames[name]);
|
|
|
|
if (data >= 0) {
|
|
|
|
log0(" %02X", data);
|
|
|
|
}
|
|
|
|
if (fail) {
|
|
|
|
log0(": failed: %d errors\n", fail);
|
|
|
|
} else {
|
|
|
|
log0(": passed\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdTest(char *params) {
|
|
|
|
unsigned int start;
|
|
|
|
unsigned int end;
|
|
|
|
int data =-100;
|
|
|
|
int i;
|
|
|
|
sscanf(params, "%x %x %d", &start, &end, &data);
|
|
|
|
if (data == -100) {
|
|
|
|
test(start, end, 0x55);
|
|
|
|
test(start, end, 0xAA);
|
|
|
|
test(start, end, 0xFF);
|
|
|
|
for (i = 0; i >= -7; i--) {
|
|
|
|
test(start, end, i);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
test(start, end, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-16 10:57:32 +00:00
|
|
|
#endif
|
|
|
|
|
2015-06-07 10:19:33 +00:00
|
|
|
void doCmdTrace(char *params) {
|
|
|
|
long i;
|
|
|
|
sscanf(params, "%ld", &i);
|
|
|
|
setTrace(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdBList(char *params) {
|
|
|
|
int i;
|
|
|
|
if (numbkpts) {
|
|
|
|
for (i = 0; i < numbkpts; i++) {
|
2015-06-19 15:10:07 +00:00
|
|
|
log0("%d: %04X mask %04X: ", i, breakpoints[i], masks[i]);
|
2015-06-10 21:31:07 +00:00
|
|
|
logMode(modes[i]);
|
2015-06-13 12:39:39 +00:00
|
|
|
log0(" (");
|
|
|
|
logTrigger(triggers[i]);
|
|
|
|
log0(")\n");
|
2015-06-07 10:19:33 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log0("No breakpoints set\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-19 15:10:07 +00:00
|
|
|
void setBreakpoint(int i, unsigned int addr, unsigned int mask, unsigned int mode, int trigger) {
|
2015-06-10 21:31:07 +00:00
|
|
|
logMode(mode);
|
|
|
|
log0(" set at %04X\n", addr);
|
2015-06-19 15:10:07 +00:00
|
|
|
breakpoints[i] = addr & mask;
|
|
|
|
masks[i] = mask;
|
2015-06-10 10:55:39 +00:00
|
|
|
modes[i] = mode;
|
2015-06-13 12:39:39 +00:00
|
|
|
triggers[i] = trigger;
|
2015-06-10 10:55:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdBreak(char *params, unsigned int mode) {
|
2015-06-07 10:19:33 +00:00
|
|
|
int i;
|
|
|
|
unsigned int addr;
|
2015-06-19 15:10:07 +00:00
|
|
|
unsigned int mask = 0xFFFF;
|
|
|
|
int trigger = -1;
|
|
|
|
sscanf(params, "%x %x %x", &addr, &mask, &trigger);
|
2015-06-07 16:58:14 +00:00
|
|
|
for (i = 0; i < numbkpts; i++) {
|
|
|
|
if (breakpoints[i] == addr) {
|
2015-06-10 10:55:39 +00:00
|
|
|
if (modes[i] & mode) {
|
2015-06-10 21:31:07 +00:00
|
|
|
logMode(mode);
|
|
|
|
log0(" already set at %04X\n", addr);
|
2015-06-10 10:55:39 +00:00
|
|
|
} else {
|
2015-06-13 12:39:39 +00:00
|
|
|
// Preserve the existing trigger, unless it is overridden
|
|
|
|
if (trigger == -1) {
|
|
|
|
trigger = triggers[i];
|
|
|
|
}
|
2015-06-19 15:10:07 +00:00
|
|
|
setBreakpoint(i, addr, mask, modes[i] | mode, trigger);
|
2015-06-10 10:55:39 +00:00
|
|
|
}
|
2015-06-07 16:58:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2015-06-10 10:55:39 +00:00
|
|
|
if (numbkpts == MAXBKPTS) {
|
2015-06-11 17:23:47 +00:00
|
|
|
log0("All %d breakpoints are already set\n", numbkpts);
|
2015-06-10 10:55:39 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-06-07 10:19:33 +00:00
|
|
|
numbkpts++;
|
2015-06-13 12:39:39 +00:00
|
|
|
// New breakpoint, so if trigger not specified, set to ALWAYS
|
|
|
|
if (trigger == -1) {
|
|
|
|
trigger = TRIGGER_ALWAYS;
|
|
|
|
}
|
2015-06-07 10:19:33 +00:00
|
|
|
for (i = numbkpts - 2; i >= -1; i--) {
|
|
|
|
if (i == -1 || breakpoints[i] < addr) {
|
2015-06-19 15:10:07 +00:00
|
|
|
setBreakpoint(i + 1, addr, mask, mode, trigger);
|
2015-06-07 10:19:33 +00:00
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
breakpoints[i + 1] = breakpoints[i];
|
2015-06-19 15:10:07 +00:00
|
|
|
masks[i + 1] = masks[i];
|
2015-06-10 10:55:39 +00:00
|
|
|
modes[i + 1] = modes[i];
|
2015-06-13 12:39:39 +00:00
|
|
|
triggers[i + 1] = triggers[i];
|
2015-06-07 10:19:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-10 10:55:39 +00:00
|
|
|
void doCmdBreakI(char *params) {
|
2015-06-20 11:30:18 +00:00
|
|
|
doCmdBreak(params, 1 << BRKPT_EXEC);
|
2015-06-10 10:55:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdBreakR(char *params) {
|
2015-06-10 21:31:07 +00:00
|
|
|
doCmdBreak(params, 1 << BRKPT_READ);
|
2015-06-10 10:55:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdBreakW(char *params) {
|
2015-06-10 21:31:07 +00:00
|
|
|
doCmdBreak(params, 1 << BRKPT_WRITE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdWatchI(char *params) {
|
2015-06-20 11:30:18 +00:00
|
|
|
doCmdBreak(params, 1 << WATCH_EXEC);
|
2015-06-10 21:31:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdWatchR(char *params) {
|
|
|
|
doCmdBreak(params, 1 << WATCH_READ);
|
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdWatchW(char *params) {
|
|
|
|
doCmdBreak(params, 1 << WATCH_WRITE);
|
2015-06-10 10:55:39 +00:00
|
|
|
}
|
|
|
|
|
2015-06-10 11:53:53 +00:00
|
|
|
void doCmdBClear(char *params, unsigned int mode) {
|
2015-06-07 10:19:33 +00:00
|
|
|
int i;
|
2015-06-13 12:39:39 +00:00
|
|
|
int n = lookupBreakpoint(params);
|
|
|
|
if (n < 0) {
|
|
|
|
return;
|
2015-06-10 11:53:53 +00:00
|
|
|
}
|
2015-06-13 12:39:39 +00:00
|
|
|
if (modes[n] & mode) {
|
|
|
|
log0("Removing ");
|
|
|
|
logMode(mode);
|
|
|
|
log0(" at %04X\n", breakpoints[n]);
|
|
|
|
modes[n] &= ~mode;
|
|
|
|
if (modes[n] == 0) {
|
|
|
|
for (i = n; i < numbkpts; i++) {
|
|
|
|
breakpoints[i] = breakpoints[i + 1];
|
2015-06-19 15:10:07 +00:00
|
|
|
masks[i] = masks[i + 1];
|
2015-06-13 12:39:39 +00:00
|
|
|
modes[i] = modes[i + 1];
|
|
|
|
triggers[i] = triggers[i + 1];
|
2015-06-10 11:53:53 +00:00
|
|
|
}
|
2015-06-13 12:39:39 +00:00
|
|
|
numbkpts--;
|
2015-06-07 10:19:33 +00:00
|
|
|
}
|
2015-06-10 11:53:53 +00:00
|
|
|
} else {
|
2015-06-10 21:31:07 +00:00
|
|
|
logMode(mode);
|
2015-06-13 12:39:39 +00:00
|
|
|
log0(" not set at %04X\n", breakpoints[n]);
|
2015-06-07 10:19:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-10 11:53:53 +00:00
|
|
|
void doCmdBClearI(char *params) {
|
2015-06-20 11:30:18 +00:00
|
|
|
doCmdBClear(params, 1 << BRKPT_EXEC);
|
2015-06-10 11:53:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdBClearR(char *params) {
|
2015-06-10 21:31:07 +00:00
|
|
|
doCmdBClear(params, 1 << BRKPT_READ);
|
2015-06-10 11:53:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdBClearW(char *params) {
|
2015-06-10 21:31:07 +00:00
|
|
|
doCmdBClear(params, 1 << BRKPT_WRITE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdWClearI(char *params) {
|
2015-06-20 11:30:18 +00:00
|
|
|
doCmdBClear(params, 1 << WATCH_EXEC);
|
2015-06-10 21:31:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdWClearR(char *params) {
|
|
|
|
doCmdBClear(params, 1 << WATCH_READ);
|
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdWClearW(char *params) {
|
|
|
|
doCmdBClear(params, 1 << WATCH_WRITE);
|
2015-06-10 11:53:53 +00:00
|
|
|
}
|
|
|
|
|
2015-06-13 12:39:39 +00:00
|
|
|
void doCmdTrigger(char *params) {
|
2015-06-16 17:41:46 +00:00
|
|
|
int trigger = -1;
|
2015-06-13 12:39:39 +00:00
|
|
|
int n = lookupBreakpoint(params);
|
|
|
|
if (n < 0) {
|
2015-06-16 17:41:46 +00:00
|
|
|
log0("Trigger Codes:\n");
|
|
|
|
for (trigger = 0; trigger < NUM_TRIGGERS; trigger++) {
|
|
|
|
log0(" %X = %s\n", trigger, triggerStrings[trigger]);
|
|
|
|
}
|
2015-06-13 12:39:39 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
sscanf(params, "%*x %x", &trigger);
|
|
|
|
if (trigger >= 0 && trigger < NUM_TRIGGERS) {
|
|
|
|
triggers[n] = trigger;
|
|
|
|
} else {
|
|
|
|
log0("Illegal trigger code (see help for trigger codes)\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-19 15:10:07 +00:00
|
|
|
void shiftBreakpointRegister(unsigned int addr, unsigned int mask, unsigned int mode, int trigger) {
|
2015-06-07 16:58:14 +00:00
|
|
|
int i;
|
2015-06-19 15:10:07 +00:00
|
|
|
for (i = 0; i <= 15; i++) {
|
|
|
|
hwCmd(CMD_LOAD_BRKPT, addr & 1);
|
|
|
|
addr >>= 1;
|
|
|
|
}
|
|
|
|
for (i = 0; i <= 15; i++) {
|
|
|
|
hwCmd(CMD_LOAD_BRKPT, mask & 1);
|
|
|
|
mask >>= 1;
|
|
|
|
}
|
|
|
|
for (i = 0; i <= 5; i++) {
|
|
|
|
hwCmd(CMD_LOAD_BRKPT, mode & 1);
|
|
|
|
mode >>= 1;
|
|
|
|
}
|
|
|
|
for (i = 0; i <= 3; i++) {
|
|
|
|
hwCmd(CMD_LOAD_BRKPT, trigger & 1);
|
|
|
|
trigger >>= 1;
|
2015-06-07 16:58:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void doCmdContinue(char *params) {
|
|
|
|
int i;
|
|
|
|
int status;
|
2015-06-16 17:41:46 +00:00
|
|
|
#ifdef LCD
|
2015-06-11 20:39:07 +00:00
|
|
|
unsigned int i_addr;
|
2015-06-16 17:41:46 +00:00
|
|
|
#endif
|
2015-06-11 17:23:47 +00:00
|
|
|
|
|
|
|
// Step the 6502, otherwise the breakpoint happends again immediately
|
|
|
|
hwCmd(CMD_STEP, 0);
|
2015-06-07 16:58:14 +00:00
|
|
|
|
|
|
|
// Disable breakpoints to allow loading
|
2015-06-10 14:49:14 +00:00
|
|
|
hwCmd(CMD_BRKPT_ENABLE, 0);
|
2015-06-07 16:58:14 +00:00
|
|
|
|
|
|
|
// Load breakpoints into comparators
|
2015-06-10 10:55:39 +00:00
|
|
|
for (i = 0; i < numbkpts; i++) {
|
2015-06-19 15:10:07 +00:00
|
|
|
shiftBreakpointRegister(breakpoints[i], masks[i], modes[i], triggers[i]);
|
2015-06-10 10:55:39 +00:00
|
|
|
}
|
|
|
|
for (i = numbkpts; i < MAXBKPTS; i++) {
|
2015-06-19 15:10:07 +00:00
|
|
|
shiftBreakpointRegister(0, 0, 0, 0);
|
2015-06-07 16:58:14 +00:00
|
|
|
}
|
|
|
|
|
2015-06-10 14:49:14 +00:00
|
|
|
// Enable breakpoints
|
|
|
|
hwCmd(CMD_BRKPT_ENABLE, 1);
|
2015-06-07 16:58:14 +00:00
|
|
|
|
|
|
|
// Disable single stepping
|
|
|
|
setSingle(0);
|
|
|
|
|
|
|
|
// Wait for breakpoint to become active
|
|
|
|
log0("6502 free running...\n");
|
2015-06-10 21:31:07 +00:00
|
|
|
int cont = 1;
|
2015-06-07 16:58:14 +00:00
|
|
|
do {
|
2015-06-11 20:39:07 +00:00
|
|
|
// Update the LCD display
|
2015-06-16 10:57:32 +00:00
|
|
|
#ifdef LCD
|
2015-06-16 17:41:46 +00:00
|
|
|
i_addr = hwRead16(OFFSET_IAL);
|
2015-06-11 20:39:07 +00:00
|
|
|
lcdAddr(i_addr);
|
2015-06-16 10:57:32 +00:00
|
|
|
#endif
|
2015-06-11 20:39:07 +00:00
|
|
|
|
2015-06-10 14:49:14 +00:00
|
|
|
status = STATUS_DIN;
|
2015-06-10 21:31:07 +00:00
|
|
|
if (status & BW_ACTIVE_MASK) {
|
|
|
|
cont = logDetails();
|
|
|
|
hwCmd(CMD_WATCH_READ, 0);
|
|
|
|
}
|
2015-06-16 10:57:32 +00:00
|
|
|
if (status & INTERRUPTED_MASK || Serial_ByteRecieved0()) {
|
2015-06-16 17:41:46 +00:00
|
|
|
log0("Interrupted\n");
|
2015-06-10 21:31:07 +00:00
|
|
|
cont = 0;
|
|
|
|
}
|
2015-06-11 17:23:47 +00:00
|
|
|
Delay_us(10);
|
2015-06-10 21:31:07 +00:00
|
|
|
} while (cont);
|
2015-06-07 16:58:14 +00:00
|
|
|
|
2015-06-16 10:57:32 +00:00
|
|
|
// Junk the interrupt character
|
|
|
|
if (Serial_ByteRecieved0()) {
|
|
|
|
Serial_RxByte0();
|
|
|
|
}
|
|
|
|
|
2015-06-07 16:58:14 +00:00
|
|
|
// Enable single stepping
|
|
|
|
setSingle(1);
|
|
|
|
|
|
|
|
// Disable breakpoints
|
2015-06-10 14:49:14 +00:00
|
|
|
hwCmd(CMD_BRKPT_ENABLE, 0);
|
2015-06-16 17:41:46 +00:00
|
|
|
|
|
|
|
// Show current instruction
|
2015-06-19 15:10:07 +00:00
|
|
|
logAddr();
|
2015-06-07 16:58:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-07 10:19:33 +00:00
|
|
|
void initialize() {
|
2015-06-10 14:49:14 +00:00
|
|
|
CTRL_DDR = 255;
|
2015-06-16 10:57:32 +00:00
|
|
|
STATUS_DDR = MUXSEL_MASK;
|
2015-06-10 14:49:14 +00:00
|
|
|
MUX_DDR = 0;
|
|
|
|
CTRL_PORT = 0;
|
2015-06-07 10:19:33 +00:00
|
|
|
Serial_Init(57600,57600);
|
2015-06-16 10:57:32 +00:00
|
|
|
#ifdef LCD
|
2015-06-07 10:19:33 +00:00
|
|
|
lcd_init();
|
|
|
|
lcd_puts("Addr: xxxx");
|
2015-06-16 10:57:32 +00:00
|
|
|
#endif
|
2015-06-07 16:58:14 +00:00
|
|
|
version();
|
2015-06-10 14:49:14 +00:00
|
|
|
hwCmd(CMD_RESET, 0);
|
2015-06-11 21:01:31 +00:00
|
|
|
hwCmd(CMD_FIFO_RST, 0);
|
2015-06-07 16:58:14 +00:00
|
|
|
setSingle(1);
|
|
|
|
setTrace(1);
|
2015-06-07 10:19:33 +00:00
|
|
|
}
|
|
|
|
|
2015-06-13 12:39:39 +00:00
|
|
|
void (*cmdFuncs[NUM_CMDS])(char *params) = {
|
2015-06-07 10:19:33 +00:00
|
|
|
doCmdHelp,
|
2015-06-20 15:41:40 +00:00
|
|
|
doCmdContinue,
|
2015-06-16 10:57:32 +00:00
|
|
|
#ifdef EMBEDDED_6502
|
|
|
|
doCmdRegs,
|
2015-06-16 17:41:46 +00:00
|
|
|
doCmdMem,
|
|
|
|
doCmdDis,
|
2015-06-17 10:17:12 +00:00
|
|
|
doCmdRead,
|
2015-06-16 17:41:46 +00:00
|
|
|
doCmdWrite,
|
2015-06-18 11:58:37 +00:00
|
|
|
doCmdFill,
|
2015-06-20 15:41:40 +00:00
|
|
|
doCmdCrc,
|
|
|
|
doCmdTest,
|
2015-06-16 10:57:32 +00:00
|
|
|
#endif
|
2015-06-07 10:19:33 +00:00
|
|
|
doCmdReset,
|
|
|
|
doCmdStep,
|
|
|
|
doCmdTrace,
|
|
|
|
doCmdBList,
|
2015-06-10 10:55:39 +00:00
|
|
|
doCmdBreakI,
|
|
|
|
doCmdBreakR,
|
|
|
|
doCmdBreakW,
|
2015-06-10 21:31:07 +00:00
|
|
|
doCmdWatchI,
|
|
|
|
doCmdWatchR,
|
|
|
|
doCmdWatchW,
|
2015-06-10 11:53:53 +00:00
|
|
|
doCmdBClearI,
|
|
|
|
doCmdBClearR,
|
|
|
|
doCmdBClearW,
|
2015-06-10 21:31:07 +00:00
|
|
|
doCmdWClearI,
|
|
|
|
doCmdWClearR,
|
|
|
|
doCmdWClearW,
|
2015-06-20 15:41:40 +00:00
|
|
|
doCmdTrigger
|
2015-06-07 10:19:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void dispatchCmd(char *cmd) {
|
|
|
|
int i;
|
|
|
|
char *cmdString;
|
|
|
|
int minLen;
|
|
|
|
int cmdStringLen;
|
|
|
|
int cmdLen = 0;
|
|
|
|
while (cmd[cmdLen] >= 'a' && cmd[cmdLen] <= 'z') {
|
|
|
|
cmdLen++;
|
|
|
|
}
|
2015-06-13 12:39:39 +00:00
|
|
|
for (i = 0; i < NUM_CMDS; i++) {
|
2015-06-07 10:19:33 +00:00
|
|
|
cmdString = cmdStrings[i];
|
|
|
|
cmdStringLen = strlen(cmdString);
|
|
|
|
minLen = cmdLen < cmdStringLen ? cmdLen : cmdStringLen;
|
|
|
|
if (strncmp(cmdString, cmd, minLen) == 0) {
|
|
|
|
(*cmdFuncs[i])(command + cmdLen);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log0("Unknown command %s\n", cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(void) {
|
|
|
|
initialize();
|
2015-06-11 17:23:47 +00:00
|
|
|
doCmdContinue(NULL);
|
2015-06-07 10:19:33 +00:00
|
|
|
while (1) {
|
|
|
|
readCmd(command);
|
|
|
|
dispatchCmd(command);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|