From 01aa860e33a7a5ff037db0ccaff828af7d21a86e Mon Sep 17 00:00:00 2001 From: loudnl Date: Fri, 24 Jan 2025 19:55:40 +0100 Subject: [PATCH] Alas, another attempt at fixing unbroken things. Arrrr! --- src/gpio.c | 102 +++++++++++++++++++++++++++------------------------ src/usbsid.c | 69 ++++++++++++++++++++++++++-------- 2 files changed, 107 insertions(+), 64 deletions(-) diff --git a/src/gpio.c b/src/gpio.c index 58e98dc..a7ea2c8 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -47,7 +47,6 @@ static int dma_tx_control, dma_tx_data, dma_rx_data, dma_tx_delay; static uint16_t control_word, delay_word; static uint32_t data_word, read_data, dir_mask; static float sidclock_frequency, busclock_frequency; -static int pico_hz = 0; static int paused_state = 0; static uint8_t volume_state[4] = {0}; @@ -109,7 +108,7 @@ void init_vu(void) void setup_piobus(void) { - pico_hz = clock_get_hz(clk_sys); + uint32_t pico_hz = clock_get_hz(clk_sys); busclock_frequency = (float)pico_hz / (usbsid_config.clock_rate * 32) / 2; /* Clock frequency is 8 times the SID clock */ CFG("[BUS CLK INIT] START\n"); @@ -273,12 +272,14 @@ int detect_clocksignal(void) /* Init nMHz square wave output */ void init_sidclock(void) { - sidclock_frequency = (float)clock_get_hz(clk_sys) / usbsid_config.clock_rate / 2; + uint32_t pico_hz = clock_get_hz(clk_sys); + sidclock_frequency = (float)pico_hz / usbsid_config.clock_rate / 2; + CFG("[SID CLK INIT] START\n"); - CFG("[PI CLK]@%.2fMHz [DIV]@%.2f [SID CLK]@%.2f [CFG SID CLK]%d\n", - pico_hz / 1000 / 1000, + CFG("[PI CLK]@%dMHz [DIV]@%.2f [SID CLK]@%.2f [CFG SID CLK]%d\n", + (pico_hz / 1000 / 1000), sidclock_frequency, - (pico_hz / sidclock_frequency / 2), + ((float)pico_hz / sidclock_frequency / 2), (int)usbsid_config.clock_rate); offset_clock = pio_add_program(bus_pio, &clock_program); sm_clock = 0; /* PIO1 SM0 */ @@ -299,71 +300,74 @@ uint8_t __not_in_flash_func(bus_operation)(uint8_t command, uint8_t address, uin if ((command & 0xF0) != 0x10) { return 0; // Sync bit not set, ignore operation } - bool is_read = (command & 0x0F) == 0x01; + int sid_command = (command & 0x0F); + bool is_read = sid_command == 0x01; pio_sm_exec(bus_pio, sm_control, pio_encode_irq_set(false, 4)); /* Preset the statemachine IRQ to not wait for a 1 */ pio_sm_exec(bus_pio, sm_data, pio_encode_irq_set(false, 5)); /* Preset the statemachine IRQ to not wait for a 1 */ - switch (command & 0x0F) { + + control_word = 0b110000; + data_word = (address & 0x3F) << 8 | data; + dir_mask = 0x0; + dir_mask |= (is_read ? 0b1111111100000000 : 0b1111111111111111); + data_word = (dir_mask << 16) | data_word; + control_word |= (is_read ? 1 : 0); + switch (address) { + case 0x00 ... 0x1F: + control_word |= one; + break; + case 0x20 ... 0x3F: + control_word |= two; + break; + case 0x40 ... 0x5F: + control_word |= three; + break; + case 0x60 ... 0x7F: + control_word |= four; + break; + } + + switch (sid_command) { case G_PAUSE: control_word = 0b110110; dma_channel_set_read_addr(dma_tx_control, &control_word, true); /* Control lines RW, CS1 & CS2 DMA transfer */ break; - case G_CLEAR_BUS: - dir_mask = 0b1111111111111111; - data_word = (dir_mask << 16) | 0x0; - dma_channel_set_read_addr(dma_tx_data, &data_word, true); /* Data & Address DMA transfer */ - break; case WRITE: sid_memory[address] = data; - case READ: - default: - control_word = 0b111000; - data_word = (address & 0x3F) << 8 | data; - dir_mask = 0x0; - dir_mask |= (is_read ? 0b1111111100000000 : 0b1111111111111111); - data_word = (dir_mask << 16) | data_word; - control_word |= (is_read ? 1 : 0); - switch (address) { - case 0x00 ... 0x1F: - control_word |= one; - break; - case 0x20 ... 0x3F: - control_word |= two; - break; - case 0x40 ... 0x5F: - control_word |= three; - break; - case 0x60 ... 0x7F: - control_word |= four; - break; - } - dma_channel_set_read_addr(dma_tx_data, &data_word, true); /* Data & Address DMA transfer */ pio_sm_exec(bus_pio, sm_data, pio_encode_wait_pin(true, 22)); - dma_channel_set_read_addr(dma_tx_control, &control_word, true); /* Control lines RW, CS1 & CS2 DMA transfer */ pio_sm_exec(bus_pio, sm_control, pio_encode_wait_pin(true, 22)); + dma_channel_set_read_addr(dma_tx_data, &data_word, true); /* Data & Address DMA transfer */ + dma_channel_set_read_addr(dma_tx_control, &control_word, true); /* Control lines RW, CS1 & CS2 DMA transfer */ break; - } - - switch (command & 0x0F) { case READ: + pio_sm_exec(bus_pio, sm_data, pio_encode_wait_pin(true, 22)); + pio_sm_exec(bus_pio, sm_control, pio_encode_wait_pin(true, 22)); + /* These are in a different order then WRITE on purpose so we actually get the read result */ + dma_channel_set_read_addr(dma_tx_control, &control_word, true); /* Control lines RW, CS1 & CS2 DMA transfer */ + dma_channel_set_read_addr(dma_tx_data, &data_word, true); /* Data & Address DMA transfer */ read_data = 0x0; dma_channel_set_write_addr(dma_rx_data, &read_data, true); dma_channel_wait_for_finish_blocking(dma_rx_data); GPIODBG("[R]$%08x 0b"PRINTF_BINARY_PATTERN_INT32" $%04x 0b"PRINTF_BINARY_PATTERN_INT16"\r\n", read_data, PRINTF_BYTE_TO_BINARY_INT32(read_data), control_word, PRINTF_BYTE_TO_BINARY_INT16(control_word)); + sid_memory[address] = (read_data >> 24) & 0xFF; return (read_data >> 24) & 0xFF; - case G_PAUSE: - case WRITE: - dma_channel_wait_for_finish_blocking(dma_tx_control); - GPIODBG("[W]$%08x 0b"PRINTF_BINARY_PATTERN_INT32" $%04x 0b"PRINTF_BINARY_PATTERN_INT16"\r\n", data_word, PRINTF_BYTE_TO_BINARY_INT32(data_word), control_word, PRINTF_BYTE_TO_BINARY_INT16(control_word)); - return 0; case G_CLEAR_BUS: - /* don't wait, just fall through */ + dir_mask = 0b1111111111111111; + data_word = (dir_mask << 16) | 0x0; + dma_channel_set_read_addr(dma_tx_data, &data_word, true); /* Data & Address DMA transfer */ + return 0; default: return 0; } + + /* WRITE & G_PAUSE */ + dma_channel_wait_for_finish_blocking(dma_tx_control); + GPIODBG("[W]$%08x 0b"PRINTF_BINARY_PATTERN_INT32" $%04x 0b"PRINTF_BINARY_PATTERN_INT16"\r\n", data_word, PRINTF_BYTE_TO_BINARY_INT32(data_word), control_word, PRINTF_BYTE_TO_BINARY_INT16(control_word)); + return 0; } void __not_in_flash_func(cycled_bus_operation)(uint8_t address, uint8_t data, uint16_t cycles) { + GPIODBG("[CB] $%02X:%02X %u\n", address, data, cycles); delay_word = cycles; if (cycles >= 1) { /* Minimum of 1 cycle as delay, otherwise unneeded overhead */ dma_channel_set_read_addr(dma_tx_delay, &delay_word, true); /* Delay cycles DMA transfer */ @@ -391,8 +395,9 @@ void __not_in_flash_func(cycled_bus_operation)(uint8_t address, uint8_t data, ui control_word |= four; break; } - dma_channel_set_read_addr(dma_tx_control, &control_word, true); /* Control lines RW, CS1 & CS2 DMA transfer */ + dma_channel_set_read_addr(dma_tx_data, &data_word, true); /* Data & Address DMA transfer */ + dma_channel_set_read_addr(dma_tx_control, &control_word, true); /* Control lines RW, CS1 & CS2 DMA transfer */ dma_channel_wait_for_finish_blocking(dma_tx_control); return; } @@ -460,6 +465,7 @@ void reset_sid(void) paused_state = 0; gpio_put(CS1, 1); gpio_put(CS2, 1); + sleep_us(10); /* 10x 02 cycles as per datasheet */ gpio_put(RES, 0); gpio_put(RES, 1); } @@ -470,7 +476,7 @@ void reset_sid_registers(void) gpio_put(CS1, 1); gpio_put(CS2, 1); gpio_put(RES, 0); - sleep_us(10); + sleep_us(10); /* 10x 02 cycles as per datasheet */ gpio_put(RES, 1); } diff --git a/src/usbsid.c b/src/usbsid.c index fb509ba..8849efd 100644 --- a/src/usbsid.c +++ b/src/usbsid.c @@ -59,7 +59,6 @@ uint8_t (*write_buffer_p)[MAX_BUFFER_SIZE] = &write_buffer; /* Config externals */ Config usbsid_config; -uint8_t sid_memory[(0x20 * 4)]; /* 4x max */ extern int sock_one, sock_two, sids_one, sids_two, numsids, act_as_one; extern void default_config(Config * config); extern void load_config(Config * config); @@ -234,7 +233,7 @@ void cdc_write(uint8_t * itf, uint32_t n) tud_cdc_n_write(*itf, write_buffer, n); /* write n bytes of data to client */ tud_cdc_n_write_flush(*itf); vu = vu == 0 ? 100 : vu; /* NOTICE: Testfix for core1 setting dtype to 0 */ - IODBG("[O] [%c] DAT[0x%02x] \r\n", dtype, write_buffer[0]); + IODBG("[O] [%c] %02X:%02X\n", dtype, sid_buffer[1], write_buffer[0]); } /* Write from device to host */ @@ -258,23 +257,36 @@ void __not_in_flash_func(handle_buffer_task)(uint8_t * itf, uint32_t * n) uint8_t n_bytes = (sid_buffer[0] & BYTE_MASK); if (command == CYCLED_WRITE) { - n_bytes = (n_bytes == 0) ? 4 : n_bytes; /* if byte count is zero, this is a single write packet */ - for (int i = 1; i <= n_bytes; i += 4) { - usbdata = 1; - if (sid_buffer[i] == 0xFF && sid_buffer[i + 1] == 0xF0 && sid_buffer[i + 2] == 0xFF && sid_buffer[i + 3] == 0xFF) { - /* EXPERIMENTAL ~ NOT WORKING YET */ - reset_sid(); - return; + // n_bytes = (n_bytes == 0) ? 4 : n_bytes; /* if byte count is zero, this is a single write packet */ + if (n_bytes == 0) { + cycled_bus_operation(sid_buffer[1], sid_buffer[2], (sid_buffer[3] << 8 | sid_buffer[4])); + } else { + for (int i = 1; i <= n_bytes; i += 4) { + usbdata = 1; + if (sid_buffer[i] == 0xFF && sid_buffer[i + 1] == 0xF0 && sid_buffer[i + 2] == 0xFF && sid_buffer[i + 3] == 0xFF) { + /* EXPERIMENTAL ~ NOT WORKING YET */ + /* reset_sid(); */ + /* return; */ + continue; + }; + cycled_bus_operation(sid_buffer[i], sid_buffer[i + 1], (sid_buffer[i + 2] << 8 | sid_buffer[i + 3])); }; - cycled_bus_operation(sid_buffer[i], sid_buffer[i + 1], (sid_buffer[i + 2] << 8 | sid_buffer[i + 3])); - }; + } return; }; if (command == WRITE) { - n_bytes = (n_bytes == 0) ? 2 : n_bytes; /* if byte count is zero, this is a single write packet */ - for (int i = 1; i <= n_bytes; i += 2) { - bus_operation(0x10, sid_buffer[i], sid_buffer[i + 1]); /* write the address and value to the SID */ - }; + // n_bytes = (n_bytes == 0) ? 2 : n_bytes; /* if byte count is zero, this is a single write packet */ + if (n_bytes == 0) { + bus_operation(0x10, sid_buffer[1], sid_buffer[2]); /* write the address and value to the SID */ + IODBG("[I] [%c] $%02X:%02X\n", dtype, sid_buffer[1], sid_buffer[2]); + } else { + IODBG("[I] [%c]", dtype); + for (int i = 1; i <= n_bytes; i += 2) { + IODBG(" $%02X:%02X", sid_buffer[i], sid_buffer[i + 1]); + bus_operation(0x10, sid_buffer[i], sid_buffer[i + 1]); /* write the address and value to the SID */ + }; + IODBG("\n"); + } return; }; if (command == READ) { /* READING CAN ONLY HANDLE ONE AT A TIME, PERIOD. */ @@ -635,7 +647,10 @@ void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) /* Handle incoming vendor and webusb data */ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - DBG("[%s] rhport:%x, stage:%x, bRequest:0x%x, wValue:%d, bittype:%x\r\n", __func__, stage, rhport, request->bRequest, request->wValue, request->bmRequestType_bit.type); + DBG("[%s] stage:%x, rhport:%x, bRequest:0x%x, wValue:%d, wIndex:%x, wLength:%x, bmRequestType:%x, type:%x, recipient:%x, direction:%x\r\n", + __func__, stage, rhport, + request->bRequest, request->wValue, request->wIndex, request->wLength, request->bmRequestType, + request->bmRequestType_bit.type, request->bmRequestType_bit.recipient, request->bmRequestType_bit.direction); /* Do nothing with IDLE (0), DATA (2) & ACK (3) stages */ if (stage != CONTROL_STAGE_SETUP) return true; /* Stage 1 */ @@ -643,6 +658,28 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ case TUSB_REQ_TYPE_STANDARD: /* 0 */ break; case TUSB_REQ_TYPE_CLASS: /* 1 */ + if (request->bRequest == WEBUSB_COMMAND) { + DBG("request->bRequest == WEBUSB_COMMAND\n"); + if (request->wValue == WEBUSB_RESET) { + DBG("request->wValue == WEBUSB_RESET\n"); + reset_sid_registers(); + unmute_sid(); + } + if (request->wValue == RESET_SID) { + DBG("request->wValue == RESET_SID\n"); + reset_sid(); + } + if (request->wValue == PAUSE) { + DBG("request->wValue == PAUSE\n"); + pause_sid(); + mute_sid(); + } + if (request->wValue == WEBUSB_CONTINUE) { + DBG("request->wValue == WEBUSB_CONTINUE\n"); + pause_sid(); + unmute_sid(); + } + } if (request->bRequest == 0x22) { /* Webserial simulates the CDC_REQUEST_SET_CONTROL_LINE_STATE (0x22) to connect and disconnect */ web_serial_connected = (request->wValue != 0);