Skip to content

Commit

Permalink
Alas, another attempt at fixing unbroken things. Arrrr!
Browse files Browse the repository at this point in the history
  • Loading branch information
LouDnl committed Jan 24, 2025
1 parent cef61fd commit 01aa860
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 64 deletions.
102 changes: 54 additions & 48 deletions src/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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 */
Expand All @@ -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 */
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}

Expand Down
69 changes: 53 additions & 16 deletions src/usbsid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand All @@ -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. */
Expand Down Expand Up @@ -635,14 +647,39 @@ 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 */

switch (request->bmRequestType_bit.type) { /* BitType */
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);
Expand Down

0 comments on commit 01aa860

Please sign in to comment.