From 57c48f1ef9c806d277bb54e480d406e0acb9c9bc Mon Sep 17 00:00:00 2001 From: Peter Weingartner Date: Sun, 11 Aug 2024 21:47:50 -0400 Subject: [PATCH] Cartridge support added Check for cartridge, identify if it's RAM or FLASH, and allow for erasing/programming the flash chip. --- src/Makefile | 4 +- src/cartridge.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cartridge.h | 43 ++++++++++++++++ src/toolbox.c | 37 ++++++++++++++ 4 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 src/cartridge.c create mode 100644 src/cartridge.h diff --git a/src/Makefile b/src/Makefile index bf20ec6..37eef00 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,7 @@ DEBUGGER=../module/Calypsi-remote-debug/src UNIT := F256K -MEMORY := ROM +MEMORY := RAM # Define OS-dependent variables @@ -51,7 +51,7 @@ else ifeq ($(UNIT),F256) else ifeq ($(UNIT),F256K) CPU=w65816 C_SRCS_DEBUGGER=$(DEBUGGER)/agent.c $(DEBUGGER)/c256-uart.c $(DEBUGGER)/low_level_WDC65816.s - SRCS_FOR_UNIT=C256/jumptable.s C256/io_stubs.c C256/extras.s C256/iecll.s C256/interrupts.s C256/f256-cstartup.s + SRCS_FOR_UNIT=cartridge.c C256/jumptable.s C256/io_stubs.c C256/extras.s C256/iecll.s C256/interrupts.s C256/f256-cstartup.s CFLAGS_FOR_UNIT=-DMODEL=17 -DCPU=255 --code-model large --data-model large ifeq ($(MEMORY),ROM) diff --git a/src/cartridge.c b/src/cartridge.c new file mode 100644 index 0000000..54cdae9 --- /dev/null +++ b/src/cartridge.c @@ -0,0 +1,129 @@ +/** + * @file cartdridge.c + * @author your name (you@domain.com) + * @brief Support for the flash cartridge + * @version 0.1 + * @date 2024-08-11 + * + * @copyright Copyright (c) 2024 + * + */ + +#include + +#include "cartridge.h" +#include "timers.h" + +volatile uint8_t * cartridge = ((volatile uint8_t *)0xf40000); + +static short cart_id_memo = CART_ID_UNDEF; + +static bool cart_rw_match(uint8_t value) { + *cartridge = value; + uint8_t new_value = *cartridge; + return (new_value == value); +} + +/** + * @brief Send a command to the flash chip + * + * @param command the number of the command + */ +static void cart_flash_command(uint8_t command) { + cartridge[0x5555] = 0xaa; + cartridge[0x2aaa] = 0x55; + cartridge[0x5555] = command; +} + +/** + * @brief Send the command to enter system ID mode on the flash chip + * + */ +static void cart_flash_system_id_enter() { + // Attempt to enter software ID mode on the flash cartridge + cart_flash_command(0x90); +} + +/** + * @brief Send the command to exit the system ID mode on the flash chip + * + */ +static void cart_flash_system_id_exit() { + // Attempt to exit software ID mode on the flash cartridge + cart_flash_command(0xf0); +} + +/** + * @brief Return a code describing the cartridge + * + * @return short the code describing the cartridge (-1 for none found) + */ +short cart_id() { + if (cart_id_memo == CART_ID_UNDEF) { + // Start off assuming we don't have anything in the slot + cart_id_memo = -1; + + // Check to see if there is RAM at the first byte of the cartridge + if (cart_rw_match(0x12) && cart_rw_match(0x23) && cart_rw_match(0x34)) { + cart_id_memo = CART_ID_RAM; + } else { + // Check to see if we have a flash chip + cart_flash_system_id_enter(); + + // Check for the manufacturer's ID we expect (BF for Microchip) + if (cartridge[0x0000] == 0xbf) { + // Yes... get the chip ID + uint8_t chip_id = cartridge[0x0001]; + if ((chip_id == 0xd5) || (chip_id == 0xd6) || (chip_id == 0xd7)) { + cart_id_memo = CART_ID_FLASH; + } + } + + // Leave system ID mode, regardless + cart_flash_system_id_exit(); + } + } + + return cart_id_memo; +} + +/** + * @brief Erase the entire flash memory + * + */ +void cart_erase() { + if (cart_id() == CART_ID_FLASH) { + cart_flash_command(0x80); + cart_flash_command(0x10); + + // Wait half a second + long target_jiffies = timers_jiffies() + 30; + while (timers_jiffies() < target_jiffies) ; + } +} + +/** + * @brief Write a byte to the flash memory + * + * @param address the address to write to (in CPU address space) + * @param value the byte to write to the address + */ +void cart_write(uint32_t address, uint8_t value) { + uint32_t cart_base_address = (uint32_t)cartridge; + uint32_t cart_end_address = 0xf7ffff; + uint8_t current_value = 0; + + if (cart_id() == CART_ID_FLASH) { + if ((cart_base_address <= address) && (cart_end_address >= address)) { + cart_flash_command(0xa0); + + // Attempt to write the data + volatile uint8_t * dest = ((volatile uint8_t *)address); + *dest = value; + + // Wait for the value to show up at the destination + long target_jiffies = timers_jiffies() + 5; + while (timers_jiffies() < target_jiffies) ; + } + } +} diff --git a/src/cartridge.h b/src/cartridge.h new file mode 100644 index 0000000..e41951e --- /dev/null +++ b/src/cartridge.h @@ -0,0 +1,43 @@ +/** + * @file cartridge.h + * @author your name (you@domain.com) + * @brief Support for the flash cartridge + * @version 0.1 + * @date 2024-08-11 + * + * @copyright Copyright (c) 2024 + * + */ + +#ifndef __cartridge_h__ +#define __cartridge_h__ + +#include + +#define CART_ID_UNDEF -2 +#define CART_ID_NONE -1 +#define CART_ID_RAM 0 +#define CART_ID_FLASH 1 + +/** + * @brief Return a code describing the cartridge + * + * @return short the code describing the cartridge (-1 for none found) + */ +extern short cart_id(); + +/** + * @brief Erase the entire flash memory + * + */ +extern void cart_erase(); + +/** + * @brief Write a byte to the flash memory + * + * @param address the address to write to (in CPU address space) + * @param value the byte to write to the address + */ +extern void cart_write(uint32_t address, uint8_t value); + +#endif \ No newline at end of file diff --git a/src/toolbox.c b/src/toolbox.c index fb48339..ff7f43e 100644 --- a/src/toolbox.c +++ b/src/toolbox.c @@ -34,6 +34,7 @@ #include "dev/txt_c256.h" #include "dev/txt_evid.h" #elif MODEL == MODEL_FOENIX_F256 || MODEL == MODEL_FOENIX_F256K || MODEL == MODEL_FOENIX_F256K2 +#include "cartridge.h" #include "dev/txt_f256.h" #include "dev/kbd_f256.h" #include "dev/sdc_f256.h" @@ -481,6 +482,42 @@ int main(int argc, char * argv[]) { test_sysinfo(); printf("Foenix Toolbox v%d.%04d.%04d\n", VER_MAJOR, VER_MINOR, VER_BUILD); + + const char * test_data = "Hello, world!"; + + volatile uint8_t * cartridge = ((volatile uint8_t *)0xf40000); + + short cartridge_id = cart_id(); + switch(cartridge_id) { + case CART_ID_NONE: + printf("No cartridge detected.\n"); + break; + + case CART_ID_RAM: + printf("RAM cartridge detected.\n"); + break; + + case CART_ID_FLASH: + printf("FLASH cartridge detected.\n"); + // printf("Attempting to erase the flash cartridge.\n"); + // cart_erase(); + // printf("Attempting to program the flash cartridge.\n"); + // for (int i = 0; i < strlen(test_data); i++) { + // cart_write(0xf40000 + i, test_data[i]); + // } + + // for (int j = 0; j < strlen(test_data); j++) { + // txt_put(0, cartridge[j]); + // } + + // printf("\n"); + break; + + default: + printf("Unable to determine whether a cartridge is present.\n"); + break; + } + test_kbd(); // printf("Initializing IEC\n");