From f7d4779880d7c3e3652af27de2e9b2c5d11815f9 Mon Sep 17 00:00:00 2001 From: David Kuder Date: Thu, 2 Mar 2023 11:05:44 -0500 Subject: [PATCH] Build 0159 Progress on PCPI mode bug fixes. PCPI mode is now working again, but the config interface is still broken enough to prevent the use of the config utility while in this mode.. Sending the FORMAT command from the monitor rom returns the card to defaults. Replace n with the slot number the card is installed in: Correction of mousetext / inverse / flashing handling on IIe see https://github.com/V2RetroComputing/analog/issues/3 ]CALL -151 *CnF0:46 4F 52 4D 41 54 00 00 Monochrome mode & color palettes are now implemented. $C0n1: Monochrome mode & palette $80: B&W $90: Inverse $A0: Amber $B0: Inverse Amber $C0: Green $D0: Inverse Green $E0: Commodore 64 Theme $F0: Use IIgs palette $C0n2: Mirror of IIgs TBCOLOR register $C0n3: Mirror of IIgs BORDER register --- v2-analog-rev1/CMakeLists.txt | 7 +- v2-analog-rev1/common/buffers.c | 5 + v2-analog-rev1/common/buffers.h | 12 +- v2-analog-rev1/common/config.c | 38 +-- v2-analog-rev1/common/main.c | 90 ++++--- v2-analog-rev1/common/usb_descriptors.c | 238 ++++++++++++++++++ v2-analog-rev1/fs/businterface.c | 2 +- v2-analog-rev1/parallel/grappler_rom.h | 2 +- v2-analog-rev1/serial/businterface.c | 4 +- v2-analog-rev1/serial/serial.c | 35 +-- v2-analog-rev1/serial/serialbuffer.c | 1 - v2-analog-rev1/serial/serialbuffer.h | 2 - v2-analog-rev1/serial/serialrom.h | 2 +- v2-analog-rev1/tusb_config.h | 114 +++++++++ v2-analog-rev1/vga/.render_test.c.swp | Bin 0 -> 1024 bytes v2-analog-rev1/vga/businterface.c | 104 ++++---- v2-analog-rev1/vga/render.c | 37 ++- v2-analog-rev1/vga/render.h | 14 +- .../vga/{render_videx.c => render_80col.c} | 10 +- v2-analog-rev1/vga/render_dgr.c | 47 +++- v2-analog-rev1/vga/render_dhgr.c | 15 +- v2-analog-rev1/vga/render_hires.c | 8 +- v2-analog-rev1/vga/render_lores.c | 71 ++++-- v2-analog-rev1/vga/render_test.c | 10 +- v2-analog-rev1/vga/render_text.c | 20 +- v2-analog-rev1/vga/vgabuf.c | 11 +- v2-analog-rev1/vga/vgabuf.h | 9 +- v2-analog-rev1/vga/vgamain.c | 2 +- v2-analog-rev1/vga/vgaout.c | 68 ++--- v2-analog-rev1/vga/vgaout.h | 2 +- v2-analog-rev1/z80/businterface.c | 5 +- v2-analog-rev1/z80/z80main.c | 4 +- 32 files changed, 719 insertions(+), 270 deletions(-) create mode 100644 v2-analog-rev1/common/usb_descriptors.c create mode 100644 v2-analog-rev1/tusb_config.h create mode 100644 v2-analog-rev1/vga/.render_test.c.swp rename v2-analog-rev1/vga/{render_videx.c => render_80col.c} (89%) diff --git a/v2-analog-rev1/CMakeLists.txt b/v2-analog-rev1/CMakeLists.txt index 227bfb5..819d7e0 100644 --- a/v2-analog-rev1/CMakeLists.txt +++ b/v2-analog-rev1/CMakeLists.txt @@ -32,6 +32,7 @@ target_sources(v2-analog-${PICO_BOARD} PUBLIC common/abus.c common/config.c common/main.c + common/usb_descriptors.c diag/businterface.c diag/diag.c fs/businterface.c @@ -43,7 +44,7 @@ target_sources(v2-analog-${PICO_BOARD} PUBLIC vga/render_hires.c vga/render_lores.c vga/render_text.c - vga/render_videx.c + vga/render_80col.c vga/render_dhgr.c vga/render_dgr.c vga/render_shr.c @@ -69,6 +70,10 @@ target_link_libraries(v2-analog-${PICO_BOARD} PUBLIC pico_multicore pico_stdlib littlefs-lib + tinyusb_device + tinyusb_board + hardware_resets + hardware_irq hardware_dma hardware_pio ) diff --git a/v2-analog-rev1/common/buffers.c b/v2-analog-rev1/common/buffers.c index f3f49e3..0749dda 100644 --- a/v2-analog-rev1/common/buffers.c +++ b/v2-analog-rev1/common/buffers.c @@ -1,5 +1,10 @@ #include "buffers.h" +volatile uint32_t soft_switches = 0; +volatile uint32_t internal_flags = 0; + +volatile uint8_t reset_state = 0; + volatile uint8_t cardslot = 0; volatile uint32_t busactive = 0; diff --git a/v2-analog-rev1/common/buffers.h b/v2-analog-rev1/common/buffers.h index e84ff4c..6ba9e2f 100644 --- a/v2-analog-rev1/common/buffers.h +++ b/v2-analog-rev1/common/buffers.h @@ -2,6 +2,8 @@ #include +extern volatile uint8_t reset_state; + extern volatile uint8_t cardslot; extern volatile uint32_t busactive; @@ -57,6 +59,8 @@ extern volatile uint8_t *videx_page; extern volatile uint32_t soft_switches; +extern volatile uint32_t internal_flags; + #define SOFTSW_TEXT_MODE 0x00000001 #define SOFTSW_MIX_MODE 0x00000002 #define SOFTSW_HIRES_MODE 0x00000004 @@ -94,7 +98,7 @@ extern volatile uint32_t soft_switches; #define SOFTSW_SHADOW_IO 0x04000000 // V2 Analog specific softswitches -#define SOFTSW_VIDEX 0x10000000 -#define SOFTSW_TEST 0x20000000 -#define SOFTSW_IIE_REGS 0x40000000 -#define SOFTSW_IIGS_REGS 0x80000000 +#define SOFTSW_TERMINAL 0x10000000 +#define IFLAGS_TEST 0x20000000 +#define IFLAGS_IIE_REGS 0x40000000 +#define IFLAGS_IIGS_REGS 0x80000000 diff --git a/v2-analog-rev1/common/config.c b/v2-analog-rev1/common/config.c index 5cc2c5a..48cac84 100644 --- a/v2-analog-rev1/common/config.c +++ b/v2-analog-rev1/common/config.c @@ -44,17 +44,17 @@ void parse_config(uint8_t *buffer) { cfg_machine = MACHINE_AUTO; } else if(!strcmp("II", buffer+2)) { cfg_machine = MACHINE_II; - soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS); + internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS); } else if(!strcmp("IIE", buffer+2)) { cfg_machine = MACHINE_IIE; - soft_switches &= ~SOFTSW_IIGS_REGS; - soft_switches |= SOFTSW_IIE_REGS; + internal_flags &= ~IFLAGS_IIGS_REGS; + internal_flags |= IFLAGS_IIE_REGS; } else if(!strcmp("IIGS", buffer+2)) { cfg_machine = MACHINE_IIGS; - soft_switches |= SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS; + internal_flags |= IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS; } else if(!strcmp("PRAVETZ", buffer+2)) { cfg_machine = MACHINE_PRAVETZ; - soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS); + internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS); } } else if(!memcmp("S=", buffer, 2)) { if(!strcmp("USB", buffer+2)) { @@ -97,7 +97,7 @@ void default_config() { int make_config(uint8_t *buf, uint16_t len) { uint16_t ptr = 0; - + memset(buf, 0, len); switch(cfg_mode) { @@ -198,7 +198,7 @@ int make_config(uint8_t *buf, uint16_t len) { strcpy(buf+ptr, "WP="); strncpy(buf+ptr+2, (char*)wifi_psk, 24); ptr += 32; - + return ptr; } @@ -206,7 +206,7 @@ void write_config() { uint8_t config_temp[1024]; int config_len; config_len = make_config(config_temp, sizeof(config_temp)); - + int file = pico_open("config", LFS_O_WRONLY | LFS_O_CREAT); if(file < 0) return; @@ -246,7 +246,7 @@ void upload_config() { pico_read(file, (uint8_t*)(apple_memory + 0xC800), 1024); pico_close(file); } - + memcpy(config_errbuf, ERR_READY, sizeof(ERR_READY)); } @@ -318,27 +318,27 @@ void config_handler() { if(!memcmp("H=", (uint8_t*)config_cmdbuf, 2)) { if(!strcmp("II", config_cmdbuf+2)) { current_machine = MACHINE_II; - soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS); + internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS); } else if(!strcmp("IIE", config_cmdbuf+2)) { current_machine = MACHINE_IIE; - soft_switches &= ~SOFTSW_IIGS_REGS; - soft_switches |= SOFTSW_IIE_REGS; + internal_flags &= ~IFLAGS_IIGS_REGS; + internal_flags |= IFLAGS_IIE_REGS; } else if(!strcmp("IIGS", config_cmdbuf+2)) { current_machine = MACHINE_IIGS; - soft_switches |= SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS; + internal_flags |= IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS; #if 0 } else if(!strcmp("B108", config_cmdbuf+2)) { current_machine = MACHINE_BASIS; - soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS); + internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS); } else if(!strcmp("P", config_cmdbuf+2)) { current_machine = MACHINE_PRAVETZ; - soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS); + internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS); } else if(!strcmp("A7", config_cmdbuf+2)) { current_machine = MACHINE_AGAT7; - soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS); + internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS); } else if(!strcmp("A9", config_cmdbuf+2)) { current_machine = MACHINE_AGAT9; - soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS); + internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS); #endif } } else if(!memcmp("UF", (uint8_t*)config_cmdbuf, 2)) { @@ -354,7 +354,9 @@ void config_handler() { } else if(!memcmp("FORMAT", (uint8_t*)config_cmdbuf, 6)) { config_format(); flash_reboot(); + } else if(!memcmp("RB", (uint8_t*)config_cmdbuf, 2)) { + flash_reboot(); } - + memset(config_cmdbuf, 0x00, 7); } diff --git a/v2-analog-rev1/common/main.c b/v2-analog-rev1/common/main.c index 27c7456..3da2197 100644 --- a/v2-analog-rev1/common/main.c +++ b/v2-analog-rev1/common/main.c @@ -13,6 +13,9 @@ #include #endif +typedef void (*businterface_t)(uint32_t address, uint32_t value); +volatile businterface_t businterface = NULL; + static void __time_critical_func(core1_loop)() { for(;;) { uint32_t value = pio_sm_get_blocking(CONFIG_ABUS_PIO, ABUS_MAIN_SM); @@ -21,10 +24,11 @@ static void __time_critical_func(core1_loop)() { // device read access if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) != 0) { if(CARD_SELECT) { - pio_sm_put_blocking(CONFIG_ABUS_PIO, ABUS_DEVICE_READ_SM, apple_memory[address]); + pio_sm_put(CONFIG_ABUS_PIO, ABUS_DEVICE_READ_SM, apple_memory[address]); + //pio_sm_put_blocking(CONFIG_ABUS_PIO, ABUS_DEVICE_READ_SM, apple_memory[address]); } } - + busactive = 1; if(CARD_SELECT) { @@ -38,52 +42,56 @@ static void __time_critical_func(core1_loop)() { apple_memory[address] = value; } } - } - - switch(current_mode) { - case MODE_DIAG: - diag_businterface(address, value); - break; - case MODE_FS: - fs_businterface(address, value); - break; - case MODE_VGACARD: - vga_businterface(address, value); - break; - case MODE_APPLICARD: - z80_businterface(address, value); - break; - case MODE_SERIAL: - serial_businterface(address, value); - break; - case MODE_PARALLEL: - parallel_businterface(address, value); - break; - } - - if(current_machine == MACHINE_AUTO) { + } else if(current_machine == MACHINE_AUTO) { if((apple_memory[0x0417] == 0xE7) && (apple_memory[0x416] == 0xC9)) { // Apple IIgs current_machine = MACHINE_IIGS; - soft_switches &= ~SOFTSW_IIE_REGS; - soft_switches |= SOFTSW_IIGS_REGS; + internal_flags &= ~IFLAGS_IIE_REGS; + internal_flags |= IFLAGS_IIGS_REGS; } else if((apple_memory[0x0417] == 0xE5) && (apple_memory[0x416] == 0xAF)) { // Apple //e Enhanced current_machine = MACHINE_IIE; - soft_switches |= SOFTSW_IIE_REGS; - soft_switches &= ~SOFTSW_IIGS_REGS; + internal_flags |= IFLAGS_IIE_REGS; + internal_flags &= ~IFLAGS_IIGS_REGS; } else if((apple_memory[0x0415] == 0xDD) && (apple_memory[0x413] == 0xE5)) { // Apple //e Unenhanced current_machine = MACHINE_IIE; - soft_switches |= SOFTSW_IIE_REGS; - soft_switches &= ~SOFTSW_IIGS_REGS; + internal_flags |= IFLAGS_IIE_REGS; + internal_flags &= ~IFLAGS_IIGS_REGS; } else if(apple_memory[0x0410] == 0xD0) { // Apple II/Plus/J-Plus with Autostart current_machine = MACHINE_II; - soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS); + internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS); } else if((apple_memory[0x07D0] == 0xAA) && (apple_memory[0x07D1] == 0x60)) { // Apple II without Autostart current_machine = MACHINE_II; - soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS); + internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS); } else if(apple_memory[0x0410] == 0xF2) { // Pravetz! current_machine = MACHINE_PRAVETZ; - soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS); + internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS); } + } else switch(reset_state) { + case 0: + if(value == ((0xFFFC << 10) | 0x300 | 0x62)) + reset_state++; + break; + case 1: + if(value == ((0xFFFD << 10) | 0x300 | 0xFA)) + reset_state++; + else + reset_state=0; + break; + case 2: + if((value & 0x3FFFF00) == ((0xFA62 << 10) | 0x300)) + reset_state++; + else + reset_state=0; + break; + case 3: + soft_switches = SOFTSW_TEXT_MODE; + + default: + reset_state = 0; + break; + } + + if(businterface != NULL) { + (*businterface)(address, value); } } } @@ -92,23 +100,33 @@ static void core0_loop() { for(;;) { switch(current_mode) { case MODE_DIAG: + businterface = &diag_businterface; diagmain(); break; case MODE_FS: + businterface = &fs_businterface; fsmain(); break; default: current_mode = MODE_VGACARD; case MODE_VGACARD: + if(cardslot == 0) cardslot = 3; + businterface = &vga_businterface; vgamain(); break; case MODE_APPLICARD: + if(cardslot == 0) cardslot = 4; + businterface = &z80_businterface; z80main(); break; case MODE_SERIAL: + if(cardslot == 0) cardslot = 2; + businterface = &serial_businterface; serialmain(); break; case MODE_PARALLEL: + if(cardslot == 0) cardslot = 1; + businterface = ¶llel_businterface; parallelmain(); break; } @@ -130,7 +148,7 @@ int main() { memcpy((uint8_t*)apple_memory+0xC5F0, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFV2ANALOG", 16); memcpy((uint8_t*)apple_memory+0xC6F0, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFV2ANALOG", 16); memcpy((uint8_t*)apple_memory+0xC7F0, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFV2ANALOG", 16); - + // Sensible defaults if there is no config / fs default_config(); diff --git a/v2-analog-rev1/common/usb_descriptors.c b/v2-analog-rev1/common/usb_descriptors.c new file mode 100644 index 0000000..c9168a7 --- /dev/null +++ b/v2-analog-rev1/common/usb_descriptors.c @@ -0,0 +1,238 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "tusb.h" + + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) + +#define USB_VID 0xCafe +#define USB_BCD 0x0200 + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = USB_VID, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ +enum +{ + ITF_NUM_CDC_0 = 0, + ITF_NUM_CDC_0_DATA, + ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN) + +#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_OUT 0x02 + #define EPNUM_CDC_0_IN 0x82 + +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X + // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT + // e.g EP1 OUT & EP1 IN cannot exist together + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_OUT 0x02 + #define EPNUM_CDC_0_IN 0x83 + +#else + #define EPNUM_CDC_0_NOTIF 0x81 + #define EPNUM_CDC_0_OUT 0x02 + #define EPNUM_CDC_0_IN 0x82 + +#endif + +uint8_t const desc_fs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + + // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64), + + // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + //TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64), +}; + +#if TUD_OPT_HIGH_SPEED +// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration + +uint8_t const desc_hs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + + // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512), +}; + +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; + +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const* tud_descriptor_device_qualifier_cb(void) +{ + return (uint8_t const*) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + + // if link speed is high return fullspeed config, and vice versa + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration; +} + +#endif // highspeed + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "V2Retro", // 1: Manufacturer + "V2 Analog VGA", // 2: Product + "123456", // 3: Serials, should use chip ID + "V2 Analog CDC", // 4: CDC Interface +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void) langid; + + uint8_t chr_count; + + if ( index == 0) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + }else + { + // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > 31 ) chr_count = 31; + + // Convert ASCII string into UTF-16 + for(uint8_t i=0; i -uint8_t grappler_rom[2048] = { +static const uint8_t grappler_rom[2048] = { }; diff --git a/v2-analog-rev1/serial/businterface.c b/v2-analog-rev1/serial/businterface.c index 7ad42b0..1eb2f90 100644 --- a/v2-analog-rev1/serial/businterface.c +++ b/v2-analog-rev1/serial/businterface.c @@ -7,7 +7,7 @@ #include "serial/serialbuffer.h" static inline void __time_critical_func(serial_read)(uint32_t address) { - switch(address & 0x7) { + switch(address & 0xF) { case 8: // Read Data from RX FIFO serial_rx_advance(); break; @@ -15,7 +15,7 @@ static inline void __time_critical_func(serial_read)(uint32_t address) { } static inline void __time_critical_func(serial_write)(uint32_t address, uint32_t value) { - switch(address & 0x7) { + switch(address & 0xF) { case 8: // Write Data to TX FIFO serial_tx_push(value & 0xff); break; diff --git a/v2-analog-rev1/serial/serial.c b/v2-analog-rev1/serial/serial.c index 7992412..554660a 100644 --- a/v2-analog-rev1/serial/serial.c +++ b/v2-analog-rev1/serial/serial.c @@ -5,34 +5,41 @@ #include "common/config.h" #include "serial/businterface.h" #include "serial/serialbuffer.h" +#include "serial/serialrom.h" +#include "bsp/board.h" +#include "tusb.h" void serialmain() { - int c; + int c, i; // Copy SSC ROM memcpy((void*)(apple_memory + 0xC800), (void*)(ssc_rom), 0x800); memcpy((void*)(apple_memory + 0xC100), (void*)(ssc_rom + 0x700), 0x100); memcpy((void*)(apple_memory + 0xC200), (void*)(apple_memory + 0xC100), 0x600); + switch(serialmux) { + case SERIAL_USB: + board_init(); + tusb_init(); + break; + case SERIAL_WIFI: + break; + } + while(current_mode == MODE_SERIAL) { config_handler(); switch(serialmux) { -#if 0 case SERIAL_USB: - if(!stdio_usb_connected()) { - sleep_ms(100); - } else { - c=getchar_timeout_us(0); - if(c != PICO_ERROR_TIMEOUT) { - serial_rx_push(c); - } - if(!serial_tx_empty()) { - c = serial_tx_pop(); - putchar(c); - } + tud_task(); + if(tud_cdc_n_available(0)) { + uint8_t buf[64]; + + uint32_t count = tud_cdc_n_read(0, buf, sizeof(buf)); + + for(i = 0; i < count; i++) + serial_rx_push(buf[i]); } break; -#endif case SERIAL_WIFI: break; case SERIAL_LOOP: diff --git a/v2-analog-rev1/serial/serialbuffer.c b/v2-analog-rev1/serial/serialbuffer.c index 0b7cca3..4d5e0b6 100644 --- a/v2-analog-rev1/serial/serialbuffer.c +++ b/v2-analog-rev1/serial/serialbuffer.c @@ -1,5 +1,4 @@ #include "serial/serialbuffer.h" -#include "serial/serialrom.h" volatile uint8_t *serial_reg = apple_memory + 0xC0A0; diff --git a/v2-analog-rev1/serial/serialbuffer.h b/v2-analog-rev1/serial/serialbuffer.h index 864c02a..d93c4d4 100644 --- a/v2-analog-rev1/serial/serialbuffer.h +++ b/v2-analog-rev1/serial/serialbuffer.h @@ -3,8 +3,6 @@ #include #include "common/buffers.h" -extern uint8_t ssc_rom[2048]; - extern volatile uint8_t *serial_reg; void serial_rx_advance(); diff --git a/v2-analog-rev1/serial/serialrom.h b/v2-analog-rev1/serial/serialrom.h index c717e69..00a3982 100644 --- a/v2-analog-rev1/serial/serialrom.h +++ b/v2-analog-rev1/serial/serialrom.h @@ -1,2 +1,2 @@ -uint8_t ssc_rom[2048] = { +static const uint8_t ssc_rom[2048] = { }; diff --git a/v2-analog-rev1/tusb_config.h b/v2-analog-rev1/tusb_config.h new file mode 100644 index 0000000..e786253 --- /dev/null +++ b/v2-analog-rev1/tusb_config.h @@ -0,0 +1,114 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by board.mk +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_DEVICE_RHPORT_NUM + #define BOARD_DEVICE_RHPORT_NUM 0 +#endif + +// RHPort max operational speed can defined by board.mk +// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed +#ifndef BOARD_DEVICE_RHPORT_SPEED + #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ + CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) + #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED + #else + #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED + #endif +#endif + +// Device mode with rhport and speed defined by board.mk +#if BOARD_DEVICE_RHPORT_NUM == 0 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) +#elif BOARD_DEVICE_RHPORT_NUM == 1 + #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) +#else + #error "Incorrect RHPort configuration" +#endif + +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_HID 0 +#define CFG_TUD_CDC 1 +#define CFG_TUD_MSC 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 + +//------------- CDC -------------// + +// CDC buffer size Should be sufficient to hold data +#define CFG_TUD_CDC_RX_BUFSIZE 16 +#define CFG_TUD_CDC_TX_BUFSIZE 16 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/v2-analog-rev1/vga/.render_test.c.swp b/v2-analog-rev1/vga/.render_test.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..422d79dad4330a88beaab15703660445c9fe01f7 GIT binary patch literal 1024 zcmYc?$V<%2S1{ExVL$=9Z5SBRi!!UKaw<{8v2omkJfos~A_JVUNg|2q>FJlHC+Zia b=B1<-#h0WOm*^!UNslr|Ltr!n=o|t7V5JcL literal 0 HcmV?d00001 diff --git a/v2-analog-rev1/vga/businterface.c b/v2-analog-rev1/vga/businterface.c index d07993e..64c11cb 100644 --- a/v2-analog-rev1/vga/businterface.c +++ b/v2-analog-rev1/vga/businterface.c @@ -6,14 +6,7 @@ #include "vga/vgabuf.h" -volatile uint8_t *videx_page = videx_memory; - -static inline void __time_critical_func(videx_crtc_addr)(uint32_t value) { -} - - -static inline void __time_critical_func(videx_crtc_write)(uint32_t value) { -} +volatile uint8_t *terminal_page = terminal_memory; void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) { @@ -21,57 +14,57 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) { if((address & 0xff80) == 0xc000) { switch(address & 0x7f) { case 0x00: - if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches &= ~SOFTSW_80STORE; } break; case 0x01: - if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches |= SOFTSW_80STORE; } break; case 0x04: - if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches &= ~SOFTSW_AUX_WRITE; } break; case 0x05: - if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches |= SOFTSW_AUX_WRITE; } break; case 0x08: - if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches &= ~SOFTSW_AUXZP; } break; case 0x09: - if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches |= SOFTSW_AUXZP; } break; case 0x0c: - if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches &= ~SOFTSW_80COL; } break; case 0x0d: - if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches |= SOFTSW_80COL; } break; case 0x0e: - if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches &= ~SOFTSW_ALTCHAR; } break; case 0x0f: - if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches |= SOFTSW_ALTCHAR; } break; case 0x21: - if((SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { if(value & 0x80) { soft_switches |= SOFTSW_MONOCHROME; } else { @@ -80,22 +73,22 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) { } break; case 0x22: - if((soft_switches & SOFTSW_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & IFLAGS_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { terminal_tbcolor = value & 0xff; } break; case 0x29: - if((soft_switches & SOFTSW_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & IFLAGS_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches = (soft_switches & ~(SOFTSW_NEWVID_MASK << SOFTSW_NEWVID_SHIFT)) | ((value & SOFTSW_NEWVID_MASK) << SOFTSW_NEWVID_SHIFT); } break; case 0x34: - if((soft_switches & SOFTSW_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & IFLAGS_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { terminal_border = value & 0x0f; } break; case 0x35: - if((soft_switches & SOFTSW_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & IFLAGS_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches = (soft_switches & ~(SOFTSW_SHADOW_MASK << SOFTSW_SHADOW_SHIFT)) | ((value & SOFTSW_SHADOW_MASK) << SOFTSW_SHADOW_SHIFT); } break; @@ -124,22 +117,22 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) { soft_switches |= SOFTSW_HIRES_MODE; break; case 0x5e: - if(soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) { + if(internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) { soft_switches |= SOFTSW_DGR; } break; case 0x5f: - if(soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) { + if(internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) { soft_switches &= ~SOFTSW_DGR; } break; case 0x7e: - if((soft_switches & SOFTSW_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & IFLAGS_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches |= SOFTSW_IOUDIS; } break; case 0x7f: - if((soft_switches & SOFTSW_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((internal_flags & IFLAGS_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { soft_switches &= ~SOFTSW_IOUDIS; } break; @@ -156,7 +149,7 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) { return; } } - + if(soft_switches & SOFTSW_80STORE) { if(soft_switches & SOFTSW_PAGE_2) { if((address >= 0x400) && (address < 0x800)) { @@ -179,31 +172,40 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) { return; } -#if 0 - // Videx 80 Column Card - if(CARD_SELECT) { - if((address >= 0xC800) && (address < 0xCC00)) { - videx_page[(address & 0x3FF)] = value & 0xff; - } - - if(CARD_DEVSEL) { - switch(address & 0x01) { - case 0x0: - videx_crtc_addr(value & 0xff); - break; - case 0x1: - videx_crtc_write(value & 0xff); - break; + if(CARD_SELECT && CARD_DEVSEL) { + cardslot = (address >> 4) & 0x7; + switch(address & 0x0F) { + case 0x01: + if(value & 0x80) { + soft_switches |= SOFTSW_MONOCHROME; + } else { + soft_switches &= ~SOFTSW_MONOCHROME; } + mono_palette = (value >> 4) & 0x7; + apple_memory[address] = value; + break; + case 0x02: + terminal_tbcolor = value & 0xff; + apple_memory[address] = terminal_tbcolor; + break; + case 0x03: + terminal_border = value & 0x0f; + apple_memory[address] = terminal_border; + break; + case 0x08: + terminal_row = (value < 24) ? value : 23; + apple_memory[address] = terminal_row; + apple_memory[address+2] = terminal_memory[terminal_row*80+terminal_col]; + break; + case 0x09: + terminal_col = (value < 80) ? value : 79; + apple_memory[address] = terminal_col; + apple_memory[address+1] = terminal_memory[terminal_row*80+terminal_col]; + break; + case 0x0A: + terminal_memory[terminal_row*80+terminal_col] = value; + break; } } -#endif } - -#if 0 - // Any access to Videx I/O sets the VRAM page visible in 0xCC00-0xD000 - if(CARD_SELECT && CARD_DEVSEL) { - videx_page = videx_memory + ((address & 0x0C) << 9); - } -#endif } diff --git a/v2-analog-rev1/vga/render.c b/v2-analog-rev1/vga/render.c index 84113cb..550084a 100644 --- a/v2-analog-rev1/vga/render.c +++ b/v2-analog-rev1/vga/render.c @@ -15,6 +15,16 @@ uint16_t text_border; compat_t machinefont = MACHINE_II; bool userfont = false; +uint16_t mono_colors[14] = { + _RGB333(0x00, 0x00, 0x00), _RGB333(0xFF, 0xFF, 0xFF), // White Normal + _RGB333(0xFF, 0xFF, 0xFF), _RGB333(0x00, 0x00, 0x00), // White Inverse + _RGB333(0x00, 0x00, 0x00), _RGB333(0xFE, 0x7F, 0x00), // Amber Normal + _RGB333(0xFE, 0x7F, 0x00), _RGB333(0x00, 0x00, 0x00), // Amber Inverse + _RGB333(0x00, 0x00, 0x00), _RGB333(0x00, 0xBF, 0x00), // Green Normal + _RGB333(0x00, 0xBF, 0x00), _RGB333(0x00, 0x00, 0x00), // Green Inverse + _RGB333(0x35, 0x28, 0x79), _RGB333(0x6C, 0x5E, 0xB5), // Commodore +}; + // Initialize the character generator ROM void switch_font() { switch(current_machine) { @@ -75,7 +85,7 @@ void update_status_right(const char *str) { for(i = 0; i < len; i++) { status_line[(80-len) + i] = str[i]; } - + status_timeout = 900; } @@ -109,11 +119,11 @@ void render_init() { switch_font(); if((soft_switches & SOFTSW_MODE_MASK) == 0) - soft_switches |= SOFTSW_TEST; + internal_flags |= IFLAGS_TEST; terminal_tbcolor = 0xf0; terminal_border = 0x00; - memcpy(videx_character_rom, appleiie_character_rom, 2048); + memcpy(terminal_character_rom, appleiie_character_rom, 2048); memset(status_line, 0, sizeof(status_line)); render_test_init(); @@ -140,6 +150,7 @@ uint32_t testdone = 0; void __noinline __time_critical_func(render_loop)() { while(current_mode == MODE_VGACARD) { config_handler(); + if((busactive == 0) && (screentimeout > (15 * 60))) { vga_prepare_frame(); render_border(480); @@ -170,21 +181,27 @@ void __noinline __time_critical_func(render_loop)() { update_text_flasher(); - text_fore = lores_palette[TERMINAL_FORE]; - text_back = lores_palette[TERMINAL_BACK]; - text_border = lores_palette[TERMINAL_BORDER]; + if((soft_switches & SOFTSW_MONOCHROME) && (mono_palette != 0x7)) { + text_fore = mono_colors[mono_palette*2+1]; + text_back = mono_colors[mono_palette*2]; + text_border = (mono_palette == 0x6) ? text_fore : text_back; + } else { + text_fore = lores_palette[TERMINAL_FORE]; + text_back = lores_palette[TERMINAL_BACK]; + text_border = lores_palette[TERMINAL_BORDER]; + } - if(soft_switches & SOFTSW_TEST) { + if(internal_flags & IFLAGS_TEST) { render_testpattern(); // Automatically dismiss the test pattern when the Apple II is seen. if(((soft_switches & SOFTSW_MODE_MASK) != 0) && (testdone == 0)) { - soft_switches &= ~SOFTSW_TEST; + internal_flags &= ~IFLAGS_TEST; testdone = 1; render_about_init(); } #if 0 - } else if(soft_switches & SOFTSW_VIDEX) { - render_videx(); + } else if(soft_switches & SOFTSW_TERMINAL) { + render_terminal(); } else if(soft_switches & SOFTSW_SHR) { render_shr(); #endif diff --git a/v2-analog-rev1/vga/render.h b/v2-analog-rev1/vga/render.h index b4ac628..63e8d6e 100644 --- a/v2-analog-rev1/vga/render.h +++ b/v2-analog-rev1/vga/render.h @@ -26,8 +26,8 @@ extern void render_text40_line(bool p2, unsigned int line); extern void render_text80_line(bool p2, unsigned int line); extern void render_status_line(); -extern void render_videx(); -extern void render_videx_line(unsigned int line); +extern void render_terminal(); +extern void render_terminal_line(unsigned int line); extern void render_border(uint count); @@ -45,9 +45,17 @@ extern void render_mixed_dgr(); extern void render_shr(); -extern uint_fast32_t text_flasher_mask; +extern volatile uint_fast32_t text_flasher_mask; extern void flash_dowork(); extern void vga_init(); extern void vga_deinit(); + + +#define _RGB333(r, g, b) ( \ + (((((uint)(r) * 256 / 36) + 128) / 256) << 6) | \ + (((((uint)(g) * 256 / 36) + 128) / 256) << 3) | \ + ((((uint)(b) * 256 / 36) + 128) / 256) \ +) + diff --git a/v2-analog-rev1/vga/render_videx.c b/v2-analog-rev1/vga/render_80col.c similarity index 89% rename from v2-analog-rev1/vga/render_videx.c rename to v2-analog-rev1/vga/render_80col.c index 3f3a4f6..b59d8b4 100644 --- a/v2-analog-rev1/vga/render_videx.c +++ b/v2-analog-rev1/vga/render_80col.c @@ -5,7 +5,7 @@ #include "vgaout.h" static inline uint_fast8_t __time_critical_func(char_terminal_bits)(uint_fast8_t ch, uint_fast8_t glyph_line) { - uint_fast8_t bits = videx_character_rom[((uint_fast16_t)ch << 3) | glyph_line]; + uint_fast8_t bits = terminal_character_rom[((uint_fast16_t)ch << 3) | glyph_line]; if(ch & 0x80) { // normal character return bits & 0x7f; @@ -21,15 +21,15 @@ static inline uint_fast8_t __time_critical_func(char_terminal_bits)(uint_fast8_t } -void __time_critical_func(render_videx)() { +void __time_critical_func(render_terminal)() { for(int line=0; line < 24; line++) { - render_videx_line(line); + render_terminal_line(line); } } -void __time_critical_func(render_videx_line)(unsigned int line) { - const uint8_t *page = (const uint8_t *)videx_memory; +void __time_critical_func(render_terminal_line)(unsigned int line) { + const uint8_t *page = (const uint8_t *)terminal_memory; const uint8_t *line_buf = page + (line * 80); for(uint glyph_line=0; glyph_line < 8; glyph_line++) { diff --git a/v2-analog-rev1/vga/render_dgr.c b/v2-analog-rev1/vga/render_dgr.c index a1a6b0e..e507479 100644 --- a/v2-analog-rev1/vga/render_dgr.c +++ b/v2-analog-rev1/vga/render_dgr.c @@ -7,6 +7,7 @@ #define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2) extern uint16_t lores_palette[16]; +extern uint16_t lores_dot_pattern[16]; static void render_dgr_line(bool p2, uint line); @@ -37,7 +38,8 @@ static void __time_critical_func(render_dgr_line)(bool p2, uint line) { struct vga_scanline *sl1 = vga_prepare_scanline(); struct vga_scanline *sl2 = vga_prepare_scanline(); uint sl_pos = 0; - uint i; + uint i, j; + uint32_t color1, color2, color3, color4; const uint8_t *line_bufa = (const uint8_t *)((p2 ? text_p2 : text_p1) + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40)); const uint8_t *line_bufb = (const uint8_t *)((p2 ? text_p4 : text_p3) + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40)); @@ -49,16 +51,41 @@ static void __time_critical_func(render_dgr_line)(bool p2, uint line) { sl_pos++; } - for(i=0; i < 40; i++) { - uint32_t color1 = lores_palette[line_bufb[i] & 0xf]; - uint32_t color2 = lores_palette[(line_bufb[i] >> 4) & 0xf]; - uint32_t color3 = lores_palette[line_bufa[i] & 0xf]; - uint32_t color4 = lores_palette[(line_bufa[i] >> 4) & 0xf]; + if(soft_switches & SOFTSW_MONOCHROME) { + for(i = 0; i < 40; i++) { + color1 = lores_dot_pattern[line_bufb[i] & 0xf] << 21; + color2 = lores_dot_pattern[(line_bufb[i] >> 4) & 0xf] << 21; + color1 |= lores_dot_pattern[line_bufa[i] & 0xf] << 7; + color2 |= lores_dot_pattern[(line_bufa[i] >> 4) & 0xf] << 7; - // Each double lores pixel is 7 double hires pixels, or 7 VGA pixels wide - sl1->data[sl_pos] = (color1|THEN_EXTEND_6) | ((color3|THEN_EXTEND_6) << 16); - sl2->data[sl_pos] = (color2|THEN_EXTEND_6) | ((color4|THEN_EXTEND_6) << 16); - sl_pos++; + for(j = 0; j < 7; j++) { + uint32_t pixeldata; + + pixeldata = (color1 & 0x8000000) ? (text_fore) : (text_back); + pixeldata |= (color1 & 0x4000000) ? ((text_fore) << 16) : ((text_back) << 16); + color1 <<= 2; + sl1->data[sl_pos] = pixeldata; + + pixeldata = (color2 & 0x8000000) ? (text_fore) : (text_back); + pixeldata |= (color2 & 0x4000000) ? ((text_fore) << 16) : ((text_back) << 16); + sl2->data[sl_pos] = pixeldata; + color2 <<= 2; + + sl_pos++; + } + } + } else { + for(i=0; i < 40; i++) { + color1 = lores_palette[line_bufb[i] & 0xf]; + color2 = lores_palette[(line_bufb[i] >> 4) & 0xf]; + color3 = lores_palette[line_bufa[i] & 0xf]; + color4 = lores_palette[(line_bufa[i] >> 4) & 0xf]; + + // Each double lores pixel is 7 double hires pixels, or 7 VGA pixels wide + sl1->data[sl_pos] = (color1|THEN_EXTEND_6) | ((color3|THEN_EXTEND_6) << 16); + sl2->data[sl_pos] = (color2|THEN_EXTEND_6) | ((color4|THEN_EXTEND_6) << 16); + sl_pos++; + } } // Pad 40 pixels on the right to center horizontally diff --git a/v2-analog-rev1/vga/render_dhgr.c b/v2-analog-rev1/vga/render_dhgr.c index 51ab274..7cc036d 100644 --- a/v2-analog-rev1/vga/render_dhgr.c +++ b/v2-analog-rev1/vga/render_dhgr.c @@ -7,12 +7,6 @@ static void render_dhgr_line(bool p2, uint line); -#define _RGB333(r, g, b) ( \ - (((((uint)(r) * 256 / 36) + 128) / 256) << 6) | \ - (((((uint)(g) * 256 / 36) + 128) / 256) << 3) | \ - ((((uint)(b) * 256 / 36) + 128) / 256) \ -) - uint16_t dhgr_palette[16] = { _RGB333(0x00,0x00,0x00), // black 0000 _RGB333(0x00,0x00,0xb4), // d.blue 1000 @@ -31,7 +25,6 @@ uint16_t dhgr_palette[16] = { _RGB333(0xd8,0xd8,0x00), // yellow 0111 _RGB333(0xff,0xff,0xff), // white 1111 }; -#undef _RGB333 //#define PAGE2SEL (!(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2)) #define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2) @@ -95,9 +88,9 @@ static void __time_critical_func(render_dhgr_line)(bool p2, uint line) { if(soft_switches & SOFTSW_MONOCHROME) { // Consume 6 pixels (24 subpixel bits) for(j = 0; j < 12; j++) { - pixeldata = ((dots & 1) ? (0x1ff) : (0x000)); + pixeldata = ((dots & 1) ? (text_fore) : (text_back)); dots >>= 1; - pixeldata |= (((dots & 1) ? (0x1ff) : (0x000))) << 16; + pixeldata |= (((dots & 1) ? (text_fore) : (text_back))) << 16; dots >>= 1; sl->data[sl_pos++] = pixeldata; } @@ -124,9 +117,9 @@ static void __time_critical_func(render_dhgr_line)(bool p2, uint line) { if(soft_switches & SOFTSW_MONOCHROME) { // Consume 8 pixels (32 subpixel bits) for(j = 0; j < 16; j++) { - pixeldata = ((dots & 1) ? (0x1ff) : (0x000)); + pixeldata = ((dots & 1) ? (text_fore) : (text_back)); dots >>= 1; - pixeldata |= (((dots & 1) ? (0x1ff) : (0x000))) << 16; + pixeldata |= (((dots & 1) ? (text_fore) : (text_back))) << 16; dots >>= 1; sl->data[sl_pos++] = pixeldata; } diff --git a/v2-analog-rev1/vga/render_hires.c b/v2-analog-rev1/vga/render_hires.c index b04693e..34106f5 100644 --- a/v2-analog-rev1/vga/render_hires.c +++ b/v2-analog-rev1/vga/render_hires.c @@ -85,10 +85,10 @@ static void __time_critical_func(render_hires_line)(bool p2, uint line) { if(soft_switches & SOFTSW_MONOCHROME) { // Consume 14 dots for(j = 0; j < 7; j++) { - uint32_t pixeldata = (dots & 0x80000000) ? (0x1ff) : (0x000); - pixeldata |= (dots & 0x40000000) ? - ((uint32_t)0x1ff) << 16 : - ((uint32_t)0x000) << 16; + uint32_t pixeldata = (dots & 0x40000000) ? (text_fore) : (text_back); + pixeldata |= (dots & 0x20000000) ? + ((text_fore) << 16) : + ((text_back) << 16); dots <<= 2; sl->data[sl_pos] = pixeldata; sl_pos++; diff --git a/v2-analog-rev1/vga/render_lores.c b/v2-analog-rev1/vga/render_lores.c index b796a63..5f0dbb5 100644 --- a/v2-analog-rev1/vga/render_lores.c +++ b/v2-analog-rev1/vga/render_lores.c @@ -3,12 +3,24 @@ #include "render.h" #include "vgaout.h" - -#define _RGB333(r, g, b) ( \ - (((((uint)(r) * 256 / 36) + 128) / 256) << 6) | \ - (((((uint)(g) * 256 / 36) + 128) / 256) << 3) | \ - ((((uint)(b) * 256 / 36) + 128) / 256) \ -) +uint16_t lores_dot_pattern[16] = { + 0x0000, + 0x2222, + 0x1111, + 0x3333, + 0x0888, + 0x2AAA, + 0x1999, + 0x3BBB, + 0x0444, + 0x2666, + 0x1555, + 0x3777, + 0x0CCC, + 0x2EEE, + 0x1DDD, + 0x3FFF, +}; uint16_t lores_palette[16] = { _RGB333(0x00,0x00,0x00), // black @@ -28,7 +40,6 @@ uint16_t lores_palette[16] = { _RGB333(0x90,0xfc,0xb4), // aqua _RGB333(0xff,0xff,0xff), // white }; -#undef _RGB333 static void render_lores_line(bool p2, uint line); @@ -63,7 +74,8 @@ static void __time_critical_func(render_lores_line)(bool p2, uint line) { struct vga_scanline *sl1 = vga_prepare_scanline(); struct vga_scanline *sl2 = vga_prepare_scanline(); uint sl_pos = 0; - uint i; + uint i, j; + uint32_t color1, color2; const uint8_t *line_buf = (const uint8_t *)((p2 ? text_p2 : text_p1) + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40)); @@ -74,20 +86,39 @@ static void __time_critical_func(render_lores_line)(bool p2, uint line) { sl_pos++; } - for(i=0; i < 40; i+=2) { - uint32_t color1 = lores_palette[line_buf[i] & 0xf]; - uint32_t color2 = lores_palette[(line_buf[i] >> 4) & 0xf]; - uint32_t color3 = lores_palette[line_buf[i+1] & 0xf]; - uint32_t color4 = lores_palette[(line_buf[i+1] >> 4) & 0xf]; + if(soft_switches & SOFTSW_MONOCHROME) { + for(i = 0; i < 40; i+=2) { + color1 = lores_dot_pattern[line_buf[i] & 0xf] << 14; + color2 = lores_dot_pattern[(line_buf[i] >> 4) & 0xf] << 14; + color1 |= lores_dot_pattern[line_buf[i+1] & 0xf]; + color2 |= lores_dot_pattern[(line_buf[i+1] >> 4) & 0xf]; - // Each lores pixel is 7 hires pixels, or 14 VGA pixels wide - sl1->data[sl_pos] = (color1|THEN_EXTEND_6) | ((color1|THEN_EXTEND_6) << 16); - sl2->data[sl_pos] = (color2|THEN_EXTEND_6) | ((color2|THEN_EXTEND_6) << 16); - sl_pos++; + for(j = 0; j < 14; j++) { + uint32_t pixeldata; - sl1->data[sl_pos] = (color3|THEN_EXTEND_6) | ((color3|THEN_EXTEND_6) << 16); - sl2->data[sl_pos] = (color4|THEN_EXTEND_6) | ((color4|THEN_EXTEND_6) << 16); - sl_pos++; + pixeldata = (color1 & 0x8000000) ? (text_fore) : (text_back); + pixeldata |= (color1 & 0x4000000) ? ((text_fore) << 16) : ((text_back) << 16); + color1 <<= 2; + sl1->data[sl_pos] = pixeldata; + + pixeldata = (color2 & 0x8000000) ? (text_fore) : (text_back); + pixeldata |= (color2 & 0x4000000) ? ((text_fore) << 16) : ((text_back) << 16); + sl2->data[sl_pos] = pixeldata; + color2 <<= 2; + + sl_pos++; + } + } + } else { + for(i = 0; i < 40; i++) { + color1 = lores_palette[line_buf[i] & 0xf]; + color2 = lores_palette[(line_buf[i] >> 4) & 0xf]; + + // Each lores pixel is 7 hires pixels, or 14 VGA pixels wide + sl1->data[sl_pos] = (color1|THEN_EXTEND_6) | ((color1|THEN_EXTEND_6) << 16); + sl2->data[sl_pos] = (color2|THEN_EXTEND_6) | ((color2|THEN_EXTEND_6) << 16); + sl_pos++; + } } for(i = 0; i < 40/8; i++) { diff --git a/v2-analog-rev1/vga/render_test.c b/v2-analog-rev1/vga/render_test.c index da3acea..44e8e80 100644 --- a/v2-analog-rev1/vga/render_test.c +++ b/v2-analog-rev1/vga/render_test.c @@ -16,8 +16,8 @@ char error_message[32*24+1]; void render_test_init() { memset(error_message, ' ', 32*24); - memcpy(error_message + 0, "HW: Analog-Rev-1 ", 32); - memcpy(error_message + 32, "FW: 23-01-29-145 ", 32); + memcpy(error_message + 0, "HARDWARE: V2 Analog Rev1", 32); + memcpy(error_message + 32, "FIRMWARE: 1 Mar 2023 Build 0159", 32); memcpy(error_message + 128, " Copyright (C) 2022-2023 ", 32); memcpy(error_message + 160, " David Kuder ", 32); @@ -30,16 +30,12 @@ void render_test_init() { memcpy(error_message + 544, " Turn off power & check ", 32); memcpy(error_message + 576, " for proper card insertion. ", 32); -#ifdef RASPBERRYPI_PICO_W memcpy(error_message + 704, " serial number: ", 32); // Get Pico's Flash Serial Number (Board ID) and terminating null. memcpy(error_message + 736, " ", 8); pico_get_unique_board_id_string(error_message + 744, 17); memcpy(error_message + 760, " ", 8); -#else - memcpy(error_message + 736, " V2-Analog-LC ", 32); -#endif } // Clear the error message, in case the user sets 0x20 in terminal switches @@ -50,7 +46,7 @@ void render_about_init() { } static inline uint_fast8_t __time_critical_func(char_test_bits)(uint_fast8_t ch, uint_fast8_t glyph_line) { - uint_fast8_t bits = videx_character_rom[((uint_fast16_t)(ch & 0x7f) << 3) | glyph_line | 0x400]; + uint_fast8_t bits = terminal_character_rom[((uint_fast16_t)(ch & 0x7f) << 3) | glyph_line | 0x400]; return bits & 0x7f; } diff --git a/v2-analog-rev1/vga/render_text.c b/v2-analog-rev1/vga/render_text.c index 0a54356..8a28096 100644 --- a/v2-analog-rev1/vga/render_text.c +++ b/v2-analog-rev1/vga/render_text.c @@ -8,7 +8,7 @@ //#define PAGE2SEL (!(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2)) #define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2) -uint_fast32_t text_flasher_mask = 0; +volatile uint_fast32_t text_flasher_mask = 0; static uint64_t next_flash_tick = 0; void update_text_flasher() { @@ -32,20 +32,20 @@ void update_text_flasher() { static inline uint_fast8_t __time_critical_func(char_text_bits)(uint_fast8_t ch, uint_fast8_t glyph_line) { - uint_fast8_t bits = character_rom[((uint_fast16_t)ch << 3) | glyph_line] & 0x7f; + uint_fast8_t bits, invert; if((soft_switches & SOFTSW_ALTCHAR) || (ch & 0x80)) { - // normal character - return bits; + // normal / mousetext character + invert = 0x00; + } else { + // flashing character or inverse character + invert = (ch & 0x40) ? text_flasher_mask : 0x7f; + ch = (ch & 0x3f) | 0x80; } - if(ch & 0x40) { - // flashing character - return (bits ^ text_flasher_mask); - } + bits = character_rom[((uint_fast16_t)ch << 3) | glyph_line] & 0x7f; - // inverse character - return bits; + return bits ^ invert; } void __time_critical_func(render_text)() { diff --git a/v2-analog-rev1/vga/vgabuf.c b/v2-analog-rev1/vga/vgabuf.c index fc25f2e..3983cdb 100644 --- a/v2-analog-rev1/vga/vgabuf.c +++ b/v2-analog-rev1/vga/vgabuf.c @@ -1,13 +1,10 @@ #include "vgabuf.h" - -// Shadow copy of the Apple soft-switches -volatile uint32_t soft_switches = 0; +volatile uint32_t mono_palette = 0; // The currently programmed character generator ROM for text mode uint8_t character_rom[2048]; -uint8_t videx_character_rom[2048]; +uint8_t terminal_character_rom[2048]; -volatile uint8_t videx_crtc_reg; - -volatile uint8_t terminal_switches; +volatile uint8_t terminal_row = 0; +volatile uint8_t terminal_col = 0; diff --git a/v2-analog-rev1/vga/vgabuf.h b/v2-analog-rev1/vga/vgabuf.h index 1ec011d..01f3c87 100644 --- a/v2-analog-rev1/vga/vgabuf.h +++ b/v2-analog-rev1/vga/vgabuf.h @@ -5,13 +5,14 @@ #define text_memory text_p1 #define hires_memory hgr_p1 -#define videx_memory (private_memory+0xF000) +#define terminal_memory (private_memory+0xF000) extern uint8_t character_rom[2048]; -extern uint8_t videx_character_rom[2048]; +extern uint8_t terminal_character_rom[2048]; -extern volatile uint8_t videx_crtc_reg; -extern volatile uint8_t videx_addr; +extern volatile uint32_t mono_palette; +extern volatile uint8_t terminal_row; +extern volatile uint8_t terminal_col; #define terminal_tbcolor apple_memory[0xC022] #define terminal_border apple_memory[0xC034] diff --git a/v2-analog-rev1/vga/vgamain.c b/v2-analog-rev1/vga/vgamain.c index 26ddf15..2383f44 100644 --- a/v2-analog-rev1/vga/vgamain.c +++ b/v2-analog-rev1/vga/vgamain.c @@ -11,5 +11,5 @@ void __noinline __time_critical_func(vgamain)() { vga_init(); render_init(); render_loop(); -// vga_deinit(); + vga_stop(); } diff --git a/v2-analog-rev1/vga/vgaout.c b/v2-analog-rev1/vga/vgaout.c index 848ba15..703fd89 100644 --- a/v2-analog-rev1/vga/vgaout.c +++ b/v2-analog-rev1/vga/vgaout.c @@ -22,6 +22,8 @@ #define NUM_SCANLINE_BUFFERS 32 +static bool vga_initialized = 0; + enum { VGA_HSYNC_SM = 0, VGA_VSYNC_SM = 1, @@ -158,29 +160,37 @@ static void vga_dma_irq_handler() { void vga_init() { - spin_lock_claim(CONFIG_VGA_SPINLOCK_ID); - spin_lock_init(CONFIG_VGA_SPINLOCK_ID); + if(!vga_initialized) { + spin_lock_claim(CONFIG_VGA_SPINLOCK_ID); + spin_lock_init(CONFIG_VGA_SPINLOCK_ID); - // Setup the PIO state machines - vga_hsync_setup(CONFIG_VGA_PIO, VGA_HSYNC_SM); - vga_vsync_setup(CONFIG_VGA_PIO, VGA_VSYNC_SM); - vga_data_setup(CONFIG_VGA_PIO, VGA_DATA_SM); + // Setup the PIO state machines + vga_hsync_setup(CONFIG_VGA_PIO, VGA_HSYNC_SM); + vga_vsync_setup(CONFIG_VGA_PIO, VGA_VSYNC_SM); + vga_data_setup(CONFIG_VGA_PIO, VGA_DATA_SM); - // Setup the DMA channel for writing to the data PIO state machine - vga_dma_channel = dma_claim_unused_channel(true); - dma_channel_config c = dma_channel_get_default_config(vga_dma_channel); - channel_config_set_transfer_data_size(&c, DMA_SIZE_32); - channel_config_set_dreq(&c, pio_get_dreq(CONFIG_VGA_PIO, VGA_DATA_SM, true)); - dma_channel_configure(vga_dma_channel, &c, &CONFIG_VGA_PIO->txf[VGA_DATA_SM], NULL, 0, false); + // Setup the DMA channel for writing to the data PIO state machine + vga_dma_channel = dma_claim_unused_channel(true); + dma_channel_config c = dma_channel_get_default_config(vga_dma_channel); + channel_config_set_transfer_data_size(&c, DMA_SIZE_32); + channel_config_set_dreq(&c, pio_get_dreq(CONFIG_VGA_PIO, VGA_DATA_SM, true)); + dma_channel_configure(vga_dma_channel, &c, &CONFIG_VGA_PIO->txf[VGA_DATA_SM], NULL, 0, false); - dma_channel_set_irq0_enabled(vga_dma_channel, true); - irq_set_exclusive_handler(DMA_IRQ_0, vga_dma_irq_handler); - irq_set_enabled(DMA_IRQ_0, true); + dma_channel_set_irq0_enabled(vga_dma_channel, true); + irq_set_exclusive_handler(DMA_IRQ_0, vga_dma_irq_handler); + irq_set_enabled(DMA_IRQ_0, true); + + vga_initialized = 1; + } // Enable all state machines in sync to ensure their instruction cycles line up pio_enable_sm_mask_in_sync(CONFIG_VGA_PIO, (1 << VGA_HSYNC_SM) | (1 << VGA_VSYNC_SM) | (1 << VGA_DATA_SM)); } +void vga_stop() { + pio_set_sm_mask_enabled(CONFIG_VGA_PIO, (1 << VGA_HSYNC_SM) | (1 << VGA_VSYNC_SM) | (1 << VGA_DATA_SM), false); +} + void vga_dpms_sleep() { pio_set_sm_mask_enabled(CONFIG_VGA_PIO, (1 << VGA_HSYNC_SM) | (1 << VGA_VSYNC_SM) | (1 << VGA_DATA_SM), false); } @@ -188,34 +198,6 @@ void vga_dpms_sleep() { void vga_dpms_wake() { pio_enable_sm_mask_in_sync(CONFIG_VGA_PIO, (1 << VGA_HSYNC_SM) | (1 << VGA_VSYNC_SM) | (1 << VGA_DATA_SM)); } - -void vga_deinit() { - // Disable DMA IRQ - irq_set_enabled(DMA_IRQ_0, false); - dma_channel_set_irq0_enabled(vga_dma_channel, false); - dma_channel_abort(vga_dma_channel); - - // Release DMA channel - dma_channel_unclaim(vga_dma_channel); - - // Disable VGA state machines - pio_set_sm_mask_enabled(CONFIG_VGA_PIO, (1 << VGA_HSYNC_SM) | (1 << VGA_VSYNC_SM) | (1 << VGA_DATA_SM), false); - - // Clear PIO memory - pio_clear_instruction_memory(CONFIG_VGA_PIO); - - // Release state machines - pio_sm_unclaim(CONFIG_VGA_PIO, VGA_HSYNC_SM); - pio_sm_unclaim(CONFIG_VGA_PIO, VGA_VSYNC_SM); - pio_sm_unclaim(CONFIG_VGA_PIO, VGA_DATA_SM); - - // Release Spin Lock - spin_lock_unclaim(CONFIG_VGA_SPINLOCK_ID); - - // Reset the PIO0 block - reset_block((1 << 10)); - unreset_block((1 << 10)); -} // Set up for a new display frame void vga_prepare_frame() { diff --git a/v2-analog-rev1/vga/vgaout.h b/v2-analog-rev1/vga/vgaout.h index bb0fc77..fbee196 100644 --- a/v2-analog-rev1/vga/vgaout.h +++ b/v2-analog-rev1/vga/vgaout.h @@ -35,6 +35,6 @@ void vga_prepare_frame(); struct vga_scanline *vga_prepare_scanline(); void vga_submit_scanline(struct vga_scanline *scanline); - +void vga_stop(); void vga_dpms_sleep(); void vga_dpms_wake(); \ No newline at end of file diff --git a/v2-analog-rev1/z80/businterface.c b/v2-analog-rev1/z80/businterface.c index 59b02f2..d5efcba 100644 --- a/v2-analog-rev1/z80/businterface.c +++ b/v2-analog-rev1/z80/businterface.c @@ -46,10 +46,13 @@ static inline void __time_critical_func(pcpi_write)(uint32_t address, uint32_t v } void __time_critical_func(z80_businterface)(uint32_t address, uint32_t value) { - pcpi_reg = apple_memory + (0xC080 | (cardslot << 4)); + // Reset the Z80 when the Apple II resets + if(reset_state == 3) z80_res = 1; + // Shadow parts of the Apple's memory by observing the bus write cycles if(CARD_SELECT) { if(CARD_DEVSEL) { + pcpi_reg = apple_memory + (address & 0xFFF0); if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) { pcpi_write(address, value); } else { diff --git a/v2-analog-rev1/z80/z80main.c b/v2-analog-rev1/z80/z80main.c index 6621649..2d2099b 100644 --- a/v2-analog-rev1/z80/z80main.c +++ b/v2-analog-rev1/z80/z80main.c @@ -88,7 +88,9 @@ void z80main() { z80_res = 1; while(current_mode == MODE_APPLICARD) { - config_handler(); + if(config_cmdbuf[7] == 0) { + config_handler(); + } else if(cardslot != 0) { if(z80_res) { rom_shadow = 1;