Skip to content

Commit

Permalink
Implement march testing for SRAM
Browse files Browse the repository at this point in the history
Probably not a great test set yet, but this is a start.
  • Loading branch information
joeyparrish committed Sep 24, 2024
1 parent 9aafaaf commit 354e8ea
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 52 deletions.
52 changes: 52 additions & 0 deletions emulator-patches/kinetoscope.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#define CMD_FLIP_REGION 0x04
#define CMD_GET_ERROR 0x05
#define CMD_CONNECT_NET 0x06
#define CMD_MARCH_TEST 0x07

// NOTE: The addresses sent to us are all relative to the base of 0xA13000.
// So we only check the offset from there. All addresses are even because the
Expand Down Expand Up @@ -365,6 +366,54 @@ static void get_video_list() {
}
}

#define SRAM_BANK_SIZE_BYTES (1 << 20)

// Write a test pattern that the Sega can read and verify.
static void sram_march_test(int pass) {
uint32_t offset = (pass & 1) * SRAM_BANK_SIZE_BYTES;

switch (pass) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
for (int i = 0; i < SRAM_BANK_SIZE_BYTES; ++i) {
int bit = (i + pass / 2) % 8;
uint8_t data = 1 << bit;
write_sram(offset++, &data, 1);
}
break;

case 16:
case 17:
for (int i = 0; i < SRAM_BANK_SIZE_BYTES; ++i) {
uint8_t data = i & 0xff;
write_sram(offset++, &data, 1);
}
break;

case 18:
case 19:
for (int i = 0; i < SRAM_BANK_SIZE_BYTES; ++i) {
uint8_t data = (i & 0xff) ^ 0xff;
write_sram(offset++, &data, 1);
}
break;
}
}

static void execute_command() {
if (global_command == CMD_ECHO) {
// Used by the ROM to check for the necessary streaming hardware.
Expand All @@ -389,6 +438,9 @@ static void execute_command() {
} else if (global_command == CMD_CONNECT_NET) {
printf("Kinetoscope: CMD_CONNECT_NET\n");
// Nothing to do: already connected.
} else if (global_command == CMD_MARCH_TEST) {
printf("Kinetoscope: CMD_MARCH_TEST\n");
sram_march_test(global_arg);
} else {
report_error("Unrecognized command 0x%02X!", global_command);
}
Expand Down
4 changes: 4 additions & 0 deletions firmware/firmware.ino
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,10 @@ static void process_command(uint8_t command, uint8_t arg) {
}
break;

case KINETOSCOPE_CMD_MARCH_TEST:
sram_march_test(arg);
break;

default: {
report_error("Unrecognized command 0x%02X!", command);
break;
Expand Down
1 change: 1 addition & 0 deletions firmware/registers.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#define KINETOSCOPE_CMD_FLIP_REGION 0x04 // Switch SRAM banks for streaming
#define KINETOSCOPE_CMD_GET_ERROR 0x05 // Load error information into SRAM
#define KINETOSCOPE_CMD_CONNECT_NET 0x06 // Connect/reconnect to the network
#define KINETOSCOPE_CMD_MARCH_TEST 0x07 // Perform a march test on SRAM

void registers_init();

Expand Down
50 changes: 50 additions & 0 deletions firmware/sram.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
static int leftover = -1;
static int active_bank_pin = -1;

#define SRAM_BANK_SIZE_BYTES (1 << 20)

// Explicitly unrolled loop for 16 bits of data.
#define X16(a) { a; a; a; a; a; a; a; a; a; a; a; a; a; a; a; a; }
static inline void sram_write_word(uint16_t word_data) {
Expand Down Expand Up @@ -110,3 +112,51 @@ void sram_flush_and_release_bank() {

leftover = -1;
}

// Write a test pattern that the Sega can read and verify.
void sram_march_test(int pass) {
sram_start_bank(pass & 1);

switch (pass) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
for (int i = 0; i < SRAM_BANK_SIZE_BYTES; ++i) {
int bit = (i + pass / 2) % 8;
uint8_t data = 1 << bit;
sram_write(&data, 1);
}
break;

case 16:
case 17:
for (int i = 0; i < SRAM_BANK_SIZE_BYTES; ++i) {
uint8_t data = i & 0xff;
sram_write(&data, 1);
}
break;

case 18:
case 19:
for (int i = 0; i < SRAM_BANK_SIZE_BYTES; ++i) {
uint8_t data = (i & 0xff) ^ 0xff;
sram_write(&data, 1);
}
break;
}

sram_flush_and_release_bank();
}
2 changes: 2 additions & 0 deletions firmware/sram.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ void sram_start_bank(int bank);
void sram_write(const uint8_t *data, int num_bytes);
void sram_flush_and_release_bank();

void sram_march_test(int pass);

#endif // _KINETOSCOPE_SRAM_H
2 changes: 1 addition & 1 deletion software/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ docker run \
-v "$repo_root":/src \
-u $(id -u):$(id -g) \
-w "/src/$relative_dir" \
ghcr.io/stephane-d/sgdk:latest
ghcr.io/stephane-d/sgdk:working

# SGDK's compiler makes the output executable, but that's not appropriate.
chmod 644 $this_dir/out/rom.bin
Expand Down
Loading

0 comments on commit 354e8ea

Please sign in to comment.