mirror of
https://github.com/V2RetroComputing/analog-firmware.git
synced 2024-12-26 19:29:23 +00:00
OTA WIP
This commit is contained in:
parent
3ebdc40736
commit
20e9ff565e
@ -92,7 +92,6 @@ target_sources(v2-analog${BINARY_TAGS} PUBLIC
|
||||
common/dmacopy.c
|
||||
common/buffers.c
|
||||
common/flash.c
|
||||
common/usb_descriptors.c
|
||||
)
|
||||
|
||||
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-vga")
|
||||
@ -115,6 +114,7 @@ elseif(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-z80")
|
||||
target_sources(v2-analog${BINARY_TAGS} PUBLIC
|
||||
z80/businterface.c
|
||||
z80/z80main.c
|
||||
z80/usb_descriptors.c
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -123,8 +123,6 @@ target_link_libraries(v2-analog${BINARY_TAGS} PUBLIC
|
||||
pico_multicore
|
||||
pico_stdlib
|
||||
pico_unique_id
|
||||
tinyusb_device
|
||||
tinyusb_board
|
||||
hardware_resets
|
||||
hardware_irq
|
||||
hardware_dma
|
||||
@ -132,6 +130,13 @@ target_link_libraries(v2-analog${BINARY_TAGS} PUBLIC
|
||||
hardware_flash
|
||||
)
|
||||
|
||||
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-z80")
|
||||
target_link_libraries(v2-analog${BINARY_TAGS} PUBLIC
|
||||
tinyusb_device
|
||||
tinyusb_board
|
||||
)
|
||||
endif()
|
||||
|
||||
if(${PICO_BOARD} MATCHES "pico_w")
|
||||
target_link_libraries(v2-analog${BINARY_TAGS} PUBLIC
|
||||
pico_cyw43_arch_lwip_poll
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define CFGTOKEN_HOST_BASIS 0x00004248 // "HB\x00\x00" Basis 108
|
||||
|
||||
#define CFGTOKEN_MUX_LOOP 0x00004C53 // "SL\x00\x00" Serial Loopback
|
||||
#define CFGTOKEN_MUX_UART 0x00005353 // "SS\x00\x00" UART
|
||||
#define CFGTOKEN_MUX_USB 0x00005553 // "SU\x00\x00" USB CDC
|
||||
#define CFGTOKEN_MUX_WIFI 0x00005753 // "SW\x00\x00" WiFi Modem
|
||||
#define CFGTOKEN_MUX_PRN 0x00005053 // "SP\x00\x00" WiFi Printer
|
||||
|
@ -3,8 +3,14 @@
|
||||
#include "common/flash.h"
|
||||
#include "common/build.h"
|
||||
#include "common/dmacopy.h"
|
||||
#ifdef FUNCTION_VGA
|
||||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
#endif
|
||||
#ifdef FUNCTION_Z80
|
||||
#include "z80/z80buf.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
volatile compat_t cfg_machine = MACHINE_AUTO;
|
||||
@ -12,11 +18,17 @@ volatile compat_t current_machine = MACHINE_AUTO;
|
||||
|
||||
#ifdef FUNCTION_Z80
|
||||
volatile usbmux_t usbmux;
|
||||
volatile serialmux_t serialmux;
|
||||
volatile serialmux_t serialmux[2];
|
||||
volatile wifimode_t wifimode;
|
||||
|
||||
volatile uint8_t wifi_ssid[32];
|
||||
volatile uint8_t wifi_psk[32];
|
||||
uint8_t wifi_ssid[32];
|
||||
uint8_t wifi_psk[32];
|
||||
|
||||
uint32_t wifi_address;
|
||||
uint32_t wifi_netmask;
|
||||
|
||||
uint8_t jd_host[32];
|
||||
uint16_t jd_port;
|
||||
#endif
|
||||
|
||||
#ifdef FUNCTION_VGA
|
||||
@ -67,6 +79,9 @@ bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
|
||||
case CFGTOKEN_HOST_PRAVETZ:
|
||||
cfg_machine = MACHINE_PRAVETZ;
|
||||
break;
|
||||
case CFGTOKEN_HOST_BASIS:
|
||||
cfg_machine = MACHINE_BASIS;
|
||||
break;
|
||||
#ifdef FUNCTION_VGA
|
||||
case CFGTOKEN_MONO_00:
|
||||
mono_palette = (config[i] >> 16) & 0xF;
|
||||
@ -79,26 +94,29 @@ bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
|
||||
break;
|
||||
#else
|
||||
case CFGTOKEN_MUX_LOOP:
|
||||
serialmux = SERIAL_LOOP;
|
||||
serialmux[(config[i] >> 16) & 1] = SERIAL_LOOP;
|
||||
break;
|
||||
case CFGTOKEN_MUX_UART:
|
||||
serialmux[(config[i] >> 16) & 1] = SERIAL_UART;
|
||||
break;
|
||||
case CFGTOKEN_MUX_USB:
|
||||
serialmux = SERIAL_USB;
|
||||
serialmux[(config[i] >> 16) & 1] = SERIAL_USB;
|
||||
break;
|
||||
case CFGTOKEN_MUX_WIFI:
|
||||
serialmux = SERIAL_WIFI;
|
||||
serialmux[(config[i] >> 16) & 1] = SERIAL_WIFI;
|
||||
break;
|
||||
case CFGTOKEN_MUX_PRN:
|
||||
serialmux = SERIAL_PRINTER;
|
||||
serialmux[(config[i] >> 16) & 1] = SERIAL_PRINTER;
|
||||
break;
|
||||
case CFGTOKEN_SER_BAUD:
|
||||
//baud = config[i+1];
|
||||
break;
|
||||
case CFGTOKEN_USB_HOST:
|
||||
usbmux = USB_HOST_CDC;
|
||||
break;
|
||||
case CFGTOKEN_USB_GUEST:
|
||||
usbmux = USB_GUEST_CDC;
|
||||
sio[(config[i] >> 16) & 1].baudrate = config[i+1];
|
||||
break;
|
||||
// case CFGTOKEN_USB_HOST:
|
||||
// usbmux = USB_HOST_CDC;
|
||||
// break;
|
||||
// case CFGTOKEN_USB_GUEST:
|
||||
// usbmux = USB_GUEST_CDC;
|
||||
// break;
|
||||
// case CFGTOKEN_USB_MIDI:
|
||||
// usbmux = USB_GUEST_MIDI;
|
||||
// break;
|
||||
@ -109,25 +127,25 @@ bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
|
||||
wifimode = WIFI_CLIENT;
|
||||
break;
|
||||
case CFGTOKEN_WIFI_SSID:
|
||||
// memset((char*)wifi_ssid, 0, sizeof(wifi_ssid));
|
||||
// strncpy((char*)wifi_ssid, (char*)(config+i+1), (config[i] >> 24));
|
||||
memset((char*)wifi_ssid, 0, sizeof(wifi_ssid));
|
||||
strncpy((char*)wifi_ssid, (char*)(config+i+1), (config[i] >> 24));
|
||||
break;
|
||||
case CFGTOKEN_WIFI_PSK:
|
||||
// memset((char*)wifi_psk, 0, sizeof(wifi_psk));
|
||||
// strncpy((char*)wifi_psk, (char*)(config+i+1), (config[i] >> 24));
|
||||
memset((char*)wifi_psk, 0, sizeof(wifi_psk));
|
||||
strncpy((char*)wifi_psk, (char*)(config+i+1), (config[i] >> 24));
|
||||
break;
|
||||
case CFGTOKEN_WIFI_IP:
|
||||
// wifi_address = config[i+1];
|
||||
wifi_address = config[i+1];
|
||||
break;
|
||||
case CFGTOKEN_WIFI_NM:
|
||||
// wifi_netmask = config[i+1];
|
||||
wifi_netmask = config[i+1];
|
||||
break;
|
||||
case CFGTOKEN_JD_HOST:
|
||||
// memset((uint8_t*)jd_host, 0, sizeof(jd_host));
|
||||
// strncpy(jd_host, (char*)(config+i+1), (config[i] >> 24));
|
||||
memset((uint8_t*)jd_host, 0, sizeof(jd_host));
|
||||
strncpy(jd_host, (char*)(config+i+1), (config[i] >> 24));
|
||||
break;
|
||||
case CFGTOKEN_JD_PORT:
|
||||
// jd_port = config[i+1];
|
||||
jd_port = config[i+1];
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@ -141,7 +159,8 @@ bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
|
||||
|
||||
void DELAYED_COPY_CODE(default_config)() {
|
||||
#ifdef FUNCTION_Z80
|
||||
serialmux = SERIAL_LOOP;
|
||||
serialmux[0] = SERIAL_USB;
|
||||
serialmux[1] = SERIAL_LOOP;
|
||||
usbmux = USB_GUEST_CDC;
|
||||
wifimode = WIFI_AP;
|
||||
strcpy((char*)wifi_ssid, "V2RetroNet");
|
||||
@ -172,12 +191,21 @@ int DELAYED_COPY_CODE(make_config)(uint8_t rev) {
|
||||
case MACHINE_IIGS:
|
||||
config_temp[i++] = CFGTOKEN_HOST_IIGS;
|
||||
break;
|
||||
case MACHINE_PRAVETZ:
|
||||
config_temp[i++] = CFGTOKEN_HOST_PRAVETZ;
|
||||
break;
|
||||
case MACHINE_BASIS:
|
||||
config_temp[i++] = CFGTOKEN_HOST_BASIS;
|
||||
break;
|
||||
}
|
||||
#ifdef FUNCTION_Z80
|
||||
switch(serialmux) {
|
||||
switch(serialmux[0]) {
|
||||
case SERIAL_USB:
|
||||
config_temp[i++] = CFGTOKEN_MUX_USB;
|
||||
break;
|
||||
case SERIAL_UART:
|
||||
config_temp[i++] = CFGTOKEN_MUX_UART;
|
||||
break;
|
||||
case SERIAL_WIFI:
|
||||
config_temp[i++] = CFGTOKEN_MUX_WIFI;
|
||||
break;
|
||||
@ -189,6 +217,24 @@ int DELAYED_COPY_CODE(make_config)(uint8_t rev) {
|
||||
config_temp[i++] = CFGTOKEN_MUX_LOOP;
|
||||
break;
|
||||
}
|
||||
switch(serialmux[1]) {
|
||||
case SERIAL_USB:
|
||||
config_temp[i++] = CFGTOKEN_MUX_USB | 0x10000;
|
||||
break;
|
||||
case SERIAL_UART:
|
||||
config_temp[i++] = CFGTOKEN_MUX_UART | 0x10000;
|
||||
break;
|
||||
case SERIAL_WIFI:
|
||||
config_temp[i++] = CFGTOKEN_MUX_WIFI | 0x10000;
|
||||
break;
|
||||
case SERIAL_PRINTER:
|
||||
config_temp[i++] = CFGTOKEN_MUX_PRN | 0x10000;
|
||||
break;
|
||||
default:
|
||||
case SERIAL_LOOP:
|
||||
config_temp[i++] = CFGTOKEN_MUX_LOOP | 0x10000;
|
||||
break;
|
||||
}
|
||||
switch(usbmux) {
|
||||
case USB_HOST_CDC:
|
||||
config_temp[i++] = CFGTOKEN_USB_HOST;
|
||||
|
@ -50,12 +50,13 @@ extern volatile uint8_t terminal_border;
|
||||
#ifdef FUNCTION_Z80
|
||||
typedef enum {
|
||||
SERIAL_LOOP = 0,
|
||||
SERIAL_UART,
|
||||
SERIAL_USB,
|
||||
SERIAL_WIFI,
|
||||
SERIAL_PRINTER,
|
||||
} serialmux_t;
|
||||
|
||||
extern volatile serialmux_t serialmux;
|
||||
extern volatile serialmux_t serialmux[2];
|
||||
|
||||
typedef enum {
|
||||
USB_HOST_CDC,
|
||||
@ -71,6 +72,16 @@ typedef enum {
|
||||
} wifimode_t;
|
||||
|
||||
extern volatile wifimode_t wifimode;
|
||||
|
||||
extern uint8_t wifi_ssid[32];
|
||||
extern uint8_t wifi_psk[32];
|
||||
|
||||
extern uint32_t wifi_address;
|
||||
extern uint32_t wifi_netmask;
|
||||
|
||||
extern uint8_t jd_host[32];
|
||||
extern uint16_t jd_port;
|
||||
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
|
@ -2,7 +2,10 @@
|
||||
#include <pico/multicore.h>
|
||||
#include <hardware/watchdog.h>
|
||||
#include <hardware/resets.h>
|
||||
#include <hardware/dma.h>
|
||||
#include <hardware/flash.h>
|
||||
#include "config.h"
|
||||
#include "flash.h"
|
||||
|
||||
#ifdef RASPBERRYPI_PICO_W
|
||||
#include <pico/cyw43_arch.h>
|
||||
@ -22,3 +25,54 @@ void __time_critical_func(flash_reboot)() {
|
||||
for(;;);
|
||||
}
|
||||
|
||||
#define CRC32_INIT ((uint32_t)-1l)
|
||||
static uint8_t dummy_dst[1];
|
||||
|
||||
void __noinline __time_critical_func(flash_ota)() {
|
||||
// Get a free channel, panic() if there are none
|
||||
int chan = dma_claim_unused_channel(true);
|
||||
|
||||
// 8 bit transfers. The read address increments after each transfer but
|
||||
// the write address remains unchanged pointing to the dummy destination.
|
||||
// No DREQ is selected, so the DMA transfers as fast as it can.
|
||||
dma_channel_config c = dma_channel_get_default_config(chan);
|
||||
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
|
||||
channel_config_set_read_increment(&c, true);
|
||||
channel_config_set_write_increment(&c, false);
|
||||
|
||||
// (bit-reverse) CRC32 specific sniff set-up
|
||||
channel_config_set_sniff_enable(&c, true);
|
||||
dma_sniffer_set_data_accumulator(CRC32_INIT);
|
||||
dma_sniffer_set_output_reverse_enabled(true);
|
||||
dma_sniffer_enable(chan, DMA_SNIFF_CTRL_CALC_VALUE_CRC32R, true);
|
||||
|
||||
dma_channel_configure(
|
||||
chan, // Channel to be configured
|
||||
&c, // The configuration we just created
|
||||
dummy_dst, // The (unchanging) write address
|
||||
(void*)FLASH_OTA_AREA, // The initial read address
|
||||
FLASH_OTA_SIZE, // Total number of transfers inc. appended crc; each is 1 byte
|
||||
true // Start immediately.
|
||||
);
|
||||
|
||||
// We could choose to go and do something else whilst the DMA is doing its
|
||||
// thing. In this case the processor has nothing else to do, so we just
|
||||
// wait for the DMA to finish.
|
||||
dma_channel_wait_for_finish_blocking(chan);
|
||||
|
||||
uint32_t sniffed_crc = dma_sniffer_get_data_accumulator();
|
||||
if (0ul == sniffed_crc) {
|
||||
uint8_t *ptr = (const uint8_t *)FLASH_OTA_AREA
|
||||
uint32_t offset;
|
||||
flash_range_erase(0, FLASH_OTA_SIZE);
|
||||
|
||||
// Copy from OTA area to Boot
|
||||
for(offset = 0; offset < FLASH_OTA_SIZE; offset+=65536);
|
||||
memcpy(private_memory, ptr+offset, 65536);
|
||||
flash_range_program(offset, private_memory, 65536);
|
||||
}
|
||||
|
||||
flash_range_erase((uint32_t)(FLASH_OTA_AREA-XIP_BASE), FLASH_OTA_SIZE);
|
||||
flash_reboot();
|
||||
}
|
||||
}
|
@ -9,10 +9,11 @@
|
||||
#define FLASH_SIZE (2*1024*1024)
|
||||
#endif
|
||||
#define FLASH_TOP (XIP_BASE + FLASH_SIZE)
|
||||
#define FLASH_RESERVED (FLASH_TOP - (256*1024))
|
||||
#define FLASH_OTA_SIZE (256*1024)
|
||||
#define FLASH_OTA_AREA (FLASH_TOP - FLASH_OTA_SIZE)
|
||||
|
||||
#define CONFIG_SIZE (4*1024)
|
||||
#define FLASH_CONFIG_ONETIME (FLASH_RESERVED - CONFIG_SIZE)
|
||||
#define FLASH_CONFIG_ONETIME (FLASH_OTA_AREA - CONFIG_SIZE)
|
||||
#define FLASH_CONFIG_PRIMARY (FLASH_CONFIG_ONETIME - CONFIG_SIZE)
|
||||
#define FLASH_CONFIG_SECONDARY (FLASH_CONFIG_PRIMARY - CONFIG_SIZE)
|
||||
|
||||
|
@ -146,6 +146,13 @@ extern uint32_t __ram_delayed_copy_start__[];
|
||||
extern uint32_t __ram_delayed_copy_end__[];
|
||||
|
||||
int main() {
|
||||
#if 0
|
||||
// OTA
|
||||
if(*(uint32_t*)FLASH_RESERVED != 0xFFFFFFFF) {
|
||||
flash_ota();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Adjust system clock for better dividing into other clocks
|
||||
set_sys_clock_khz(CONFIG_SYSCLOCK*1000, true);
|
||||
|
||||
|
82
tools/mksparse.c
Normal file
82
tools/mksparse.c
Normal file
@ -0,0 +1,82 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#define CRC32_INIT ((uint32_t)-1l)
|
||||
#define BLOCK_SIZE 512
|
||||
#define FLASH_SIZE (256*1024)
|
||||
|
||||
uint8_t ota_buffer[FLASH_SIZE];
|
||||
uint8_t block_list[FLASH_SIZE/BLOCK_SIZE];
|
||||
|
||||
static uint32_t soft_crc32_block(uint32_t crc, uint8_t *bytp, uint32_t length) {
|
||||
while(length--) {
|
||||
uint32_t byte32 = (uint32_t)*bytp++;
|
||||
|
||||
for (uint8_t bit = 8; bit; bit--, byte32 >>= 1) {
|
||||
crc = (crc >> 1) ^ (((crc ^ byte32) & 1ul) ? 0xEDB88320ul : 0ul);
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
int is_solid_block(uint8_t *buffer, uint8_t ch, uint32_t size) {
|
||||
uint32_t i;
|
||||
|
||||
for(i = 0; i < size; i++) {
|
||||
if(buffer[i] != ch) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
uint32_t crc_result;
|
||||
FILE *in, *out;
|
||||
int i;
|
||||
|
||||
memset(ota_buffer, 0xff, FLASH_SIZE);
|
||||
|
||||
if(argc != 3) {
|
||||
fprintf(stderr, "Usage:\r\n\t%s <input> <output>\r\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
in = fopen(argv[1], "rb");
|
||||
if(!in) {
|
||||
fprintf(stderr, "Unable to open input file '%s'.\r\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
out = fopen(argv[2], "wb");
|
||||
if(!out) {
|
||||
fprintf(stderr, "Unable to open output file '%s'.\r\n", argv[2]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fread(ota_buffer, 1, FLASH_SIZE, in);
|
||||
fclose(in);
|
||||
|
||||
crc_result = soft_crc32_block(CRC32_INIT, ota_buffer, FLASH_SIZE-sizeof(uint32_t));
|
||||
ota_buffer[FLASH_SIZE - 4] = (crc_result >> 0) & 0xff;
|
||||
ota_buffer[FLASH_SIZE - 3] = (crc_result >> 8) & 0xff;
|
||||
ota_buffer[FLASH_SIZE - 2] = (crc_result >> 16) & 0xff;
|
||||
ota_buffer[FLASH_SIZE - 1] = (crc_result >> 24) & 0xff;
|
||||
|
||||
for(i = 0; i < (FLASH_SIZE/BLOCK_SIZE); i++) {
|
||||
block_list[i] = (is_solid_block(ota_buffer+(i*BLOCK_SIZE), 0x00, BLOCK_SIZE) ? 1 : 0) |
|
||||
(is_solid_block(ota_buffer+(i*BLOCK_SIZE), 0xff, BLOCK_SIZE) ? 2 : 0);
|
||||
}
|
||||
|
||||
fwrite(block_list, 1, (FLASH_SIZE/BLOCK_SIZE), out);
|
||||
|
||||
for(i = 0; i < (FLASH_SIZE/BLOCK_SIZE); i++) {
|
||||
if(!block_list[i])
|
||||
fwrite(ota_buffer+(i*BLOCK_SIZE), 1, BLOCK_SIZE, out);
|
||||
}
|
||||
|
||||
fclose(out);
|
||||
return 0;
|
||||
}
|
@ -96,7 +96,7 @@
|
||||
|
||||
//------------- CLASS -------------//
|
||||
#define CFG_TUD_HID 0
|
||||
#define CFG_TUD_CDC 1
|
||||
#define CFG_TUD_CDC 2
|
||||
#define CFG_TUD_MSC 0
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_VENDOR 0
|
||||
@ -104,8 +104,10 @@
|
||||
//------------- CDC -------------//
|
||||
|
||||
// CDC buffer size Should be sufficient to hold data
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE 16
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE 16
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
|
||||
#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ void __time_critical_func(z80_businterface)(uint32_t address, uint32_t value) {
|
||||
// Ideally this code should only run once.
|
||||
new_pcpi_reg = apple_memory + (address & 0xFFF0);
|
||||
if((uint32_t)new_pcpi_reg != (uint32_t)pcpi_reg) {
|
||||
memcpy(new_pcpi_reg, pcpi_reg, 16);
|
||||
memcpy((void*)new_pcpi_reg, (void*)pcpi_reg, 16);
|
||||
pcpi_reg = new_pcpi_reg;
|
||||
}
|
||||
|
||||
|
19
z80/z80buf.h
19
z80/z80buf.h
@ -19,3 +19,22 @@ extern volatile uint8_t *pcpi_reg;
|
||||
#define set_6502_stat { pcpi_reg[3] |= 0x80; }
|
||||
#define rd_6502_stat (pcpi_reg[3] >> 7)
|
||||
|
||||
typedef struct ctc_s {
|
||||
uint8_t control;
|
||||
uint8_t counter;
|
||||
uint8_t preload;
|
||||
} ctc_t;
|
||||
|
||||
extern volatile ctc_t ctc[4];
|
||||
extern volatile uint8_t ctc_vector;
|
||||
|
||||
typedef struct sio_s {
|
||||
uint8_t control[8];
|
||||
uint8_t status[2];
|
||||
uint8_t data;
|
||||
uint8_t datavalid;
|
||||
uint32_t baudrate;
|
||||
} sio_t;
|
||||
|
||||
extern volatile sio_t sio[2];
|
||||
extern volatile uint8_t sio_vector;
|
||||
|
220
z80/z80main.c
220
z80/z80main.c
@ -5,6 +5,12 @@
|
||||
#include "z80/z80buf.h"
|
||||
#include "z80/z80rom.h"
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "tusb.h"
|
||||
|
||||
// Used to ensure we interrupt the Z80 loop every 256 instructions
|
||||
volatile uint8_t z80_cycle;
|
||||
|
||||
volatile uint32_t z80_vect = 0x000000;
|
||||
volatile uint8_t __attribute__((section(".uninitialized_data."))) z80_irq;
|
||||
volatile uint8_t __attribute__((section(".uninitialized_data."))) z80_nmi;
|
||||
@ -13,45 +19,191 @@ volatile uint8_t __attribute__((section(".uninitialized_data."))) rom_shadow;
|
||||
volatile uint8_t __attribute__((section(".uninitialized_data."))) ram_bank;
|
||||
volatile uint8_t __attribute__((section(".uninitialized_data."))) ram_common;
|
||||
|
||||
#define Z80break (z80_res || (config_cmdbuf[7] == 0))
|
||||
volatile ctc_t ctc[4];
|
||||
volatile uint8_t ctc_vector;
|
||||
|
||||
volatile sio_t sio[2];
|
||||
volatile uint8_t sio_vector;
|
||||
|
||||
#define Z80break (z80_res || (config_cmdbuf[7] == 0) || (!z80_cycle++))
|
||||
|
||||
uint8_t DELAYED_COPY_CODE(cpu_in)(uint16_t address) {
|
||||
uint8_t rv = 0;
|
||||
switch(address & 0xe0) {
|
||||
case 0x00: // Write Data to 6502
|
||||
rv = pcpi_reg[0];
|
||||
break;
|
||||
case 0x20: // Read Data from 6502
|
||||
clr_z80_stat;
|
||||
rv = pcpi_reg[1];
|
||||
//printf("I%01X:%02X\r\n", (address >> 4), rv);
|
||||
break;
|
||||
case 0x40: // Status Port
|
||||
if(rd_z80_stat)
|
||||
rv |= 0x80;
|
||||
if(rd_6502_stat)
|
||||
rv |= 0x01;
|
||||
break;
|
||||
case 0x60:
|
||||
break;
|
||||
if(address & 0x80) {
|
||||
switch(address & 0xff) {
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
case 0x82:
|
||||
case 0x83:
|
||||
if(ctc[address & 0x03].control & 0x40) {
|
||||
rv = ctc[address & 0x03].counter;
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
case 0xFC:
|
||||
case 0xFE:
|
||||
switch(serialmux[(address & 0x01)]) {
|
||||
case SERIAL_LOOP:
|
||||
if(sio[(address & 0x01)].datavalid) {
|
||||
sio[(address & 0x01)].datavalid = 0;
|
||||
rv = sio[(address & 0x01)].data;
|
||||
}
|
||||
break;
|
||||
case SERIAL_USB:
|
||||
if(tud_cdc_n_available((address & 0x01))) {
|
||||
rv = tud_cdc_n_read_char((address & 0x01));
|
||||
}
|
||||
break;
|
||||
case SERIAL_UART:
|
||||
if(address & 0x01) {
|
||||
if(uart_is_readable(uart1)) {
|
||||
rv = uart_getc(uart1);
|
||||
}
|
||||
} else {
|
||||
if(uart_is_readable(uart0)) {
|
||||
rv = uart_getc(uart0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xFD:
|
||||
case 0xFF:
|
||||
switch(sio[(address & 0x01)].control[0] & 0x7) {
|
||||
case 0:
|
||||
switch(serialmux[(address & 0x01)]) {
|
||||
case SERIAL_LOOP:
|
||||
rv = ((sio[(address & 0x01)].control[5] & 0x02) ? 0x20 : 0x00) |
|
||||
((sio[(address & 0x01)].control[5] & 0x80) ? 0x08 : 0x00) |
|
||||
(sio[(address & 0x01)].datavalid ? 0x01 : 0x04);
|
||||
break;
|
||||
case SERIAL_USB:
|
||||
rv = ((tud_cdc_n_get_line_state(address & 0x01) & 2) ? 0x20 : 0x00) |
|
||||
(tud_cdc_n_connected(address & 0x01) ? 0x08 : 0x00) |
|
||||
(tud_cdc_n_write_available(address & 0x01) ? 0x04 : 0x00) |
|
||||
(tud_cdc_n_available(address & 0x01) ? 0x01 : 0x00);
|
||||
break;
|
||||
case SERIAL_UART:
|
||||
if(address & 0x01) {
|
||||
rv = 0x20 |
|
||||
(uart_is_writable(uart1) ? 0x00 : 0x04) |
|
||||
(uart_is_readable(uart1) ? 0x01 : 0x00);
|
||||
} else {
|
||||
rv = 0x20 |
|
||||
(uart_is_writable(uart0) ? 0x00 : 0x04) |
|
||||
(uart_is_readable(uart0) ? 0x01 : 0x00);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
rv = sio[(address & 0x01)].status[1];
|
||||
break;
|
||||
case 2:
|
||||
if(address & 0x01)
|
||||
rv = sio_vector;
|
||||
break;
|
||||
}
|
||||
sio[(address & 0x01)].control[0] &= 0xF8;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(address & 0xe0) {
|
||||
case 0x00: // Write Data to 6502
|
||||
rv = pcpi_reg[0];
|
||||
break;
|
||||
case 0x20: // Read Data from 6502
|
||||
clr_z80_stat;
|
||||
rv = pcpi_reg[1];
|
||||
//printf("I%01X:%02X\r\n", (address >> 4), rv);
|
||||
break;
|
||||
case 0x40: // Status Port
|
||||
if(rd_z80_stat)
|
||||
rv |= 0x80;
|
||||
if(rd_6502_stat)
|
||||
rv |= 0x01;
|
||||
break;
|
||||
case 0x60:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(cpu_out)(uint16_t address, uint8_t value) {
|
||||
switch(address & 0xe0) {
|
||||
case 0x00: // Write Data to 6502
|
||||
//printf("O%01X:%02X\r\n", (address >> 4), value);
|
||||
pcpi_reg[0] = value;
|
||||
set_6502_stat;
|
||||
break;
|
||||
case 0x60:
|
||||
rom_shadow = (value & 1);
|
||||
break;
|
||||
case 0xC0:
|
||||
ram_bank = (value >> 1) & 7;
|
||||
ram_common = (value >> 6) & 1;
|
||||
break;
|
||||
uint16_t divisor;
|
||||
if(address & 0x80) {
|
||||
switch(address & 0xff) {
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
case 0x82:
|
||||
case 0x83:
|
||||
if(ctc[address & 0x03].control & 0x04) {
|
||||
ctc[address & 0x03].control &= ~0x06;
|
||||
|
||||
ctc[address & 0x03].preload = value;
|
||||
if((address & 0x02) == 0) {
|
||||
divisor = value ? value : 256;
|
||||
sio[address & 0x01].baudrate = 115200 / divisor;
|
||||
if(serialmux[(address & 0x01)] == SERIAL_UART) {
|
||||
if(address & 0x01) {
|
||||
uart_set_baudrate(uart1, sio[1].baudrate);
|
||||
} else {
|
||||
uart_set_baudrate(uart0, sio[0].baudrate);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(value & 1) {
|
||||
ctc[address & 0x03].control = value;
|
||||
} else if((address & 0x3) == 0) {
|
||||
ctc_vector = value & 0xF8;
|
||||
}
|
||||
break;
|
||||
case 0xFC:
|
||||
case 0xFE:
|
||||
switch(serialmux[(address & 0x01)]) {
|
||||
case SERIAL_LOOP:
|
||||
if(sio[(address & 0x01)].datavalid) {
|
||||
sio[(address & 0x01)].status[1] |= 0x20;
|
||||
}
|
||||
sio[(address & 0x01)].datavalid = 1;
|
||||
sio[(address & 0x01)].data = value;
|
||||
break;
|
||||
case SERIAL_UART:
|
||||
if(tud_cdc_n_write_available(address & 0x01))
|
||||
tud_cdc_n_write_char(address & 0x01, value);
|
||||
break;
|
||||
case SERIAL_USB:
|
||||
if(uart_is_writable(uart0)) {
|
||||
uart_putc(uart0, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xFD:
|
||||
case 0xFF:
|
||||
if(((sio[(address & 0x01)].control[0] & 0x7) == 2) && (address & 0x01))
|
||||
sio_vector = value;
|
||||
|
||||
sio[(address & 0x01)].control[sio[(address & 0x01)].control[0] & 0x7] = value;
|
||||
sio[(address & 0x01)].control[0] &= 0xF8;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(address & 0xe0) {
|
||||
case 0x00: // Write Data to 6502
|
||||
//printf("O%01X:%02X\r\n", (address >> 4), value);
|
||||
pcpi_reg[0] = value;
|
||||
set_6502_stat;
|
||||
break;
|
||||
case 0x60:
|
||||
rom_shadow = (value & 1);
|
||||
break;
|
||||
case 0xC0:
|
||||
ram_bank = (value >> 1) & 7;
|
||||
ram_common = (value >> 6) & 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,7 +243,13 @@ void DELAYED_COPY_CODE(_RamWrite)(uint16_t address, uint8_t value) {
|
||||
void DELAYED_COPY_CODE(z80main)() {
|
||||
z80_res = 1;
|
||||
|
||||
board_init();
|
||||
tusb_init();
|
||||
|
||||
for(;;) {
|
||||
if(!z80_cycle) {
|
||||
tud_task();
|
||||
}
|
||||
if(config_cmdbuf[7] == 0) {
|
||||
config_handler();
|
||||
} else
|
||||
|
Loading…
Reference in New Issue
Block a user