From 4e103a2639e99207b8ae04f90fc8824043f83a4e Mon Sep 17 00:00:00 2001 From: harbaum Date: Mon, 15 Jun 2015 09:19:13 +0000 Subject: [PATCH] [FIRMWARE/ATARI ST] Initial support for pl2303 usb/rs232 cable --- cores/mist/mfp.v | 79 +++++++++++++++++++++++++++++++++++++++--- cores/mist/mfp_timer.v | 8 ++++- cores/mist/mist_top.v | 10 ++++-- cores/mist/user_io.v | 29 ++++++++++++---- 4 files changed, 112 insertions(+), 14 deletions(-) diff --git a/cores/mist/mfp.v b/cores/mist/mfp.v index ead88d7..564cbf0 100644 --- a/cores/mist/mfp.v +++ b/cores/mist/mfp.v @@ -36,11 +36,13 @@ module mfp ( output serial_data_out_available, input serial_strobe_out, output [7:0] serial_data_out, + output [63:0] serial_status_out, // serial rs223 connection from io controller input serial_strobe_in, input [7:0] serial_data_in, output serial_data_in_full, + input [7:0] serial_status_in, // inputs input clk_ext, // external 2.457MHz @@ -86,16 +88,20 @@ io_fifo mfp_in_fifo ( .out_strobe (1'b0), .out_enable (serial_cpu_data_read && serial_data_in_available), + .empty (serial_data_in_empty), .full (serial_data_in_full), .data_available (serial_data_in_available) ); // ---------------- mfp uart data to/from io controller ------------ -reg serial_cpu_data_read; +reg serial_cpu_data_read, serial_cpu_data_readD; wire serial_data_in_available; wire [7:0] serial_data_in_cpu; +wire serial_data_in_empty; always @(negedge clk) begin + serial_cpu_data_readD <= serial_cpu_data_read; + // read on uart data register serial_cpu_data_read <= 1'b0; if(sel && ~ds && rw && (addr == 5'h17)) @@ -165,6 +171,7 @@ mfp_timer timer_c ( wire timerd_done; wire [7:0] timerd_dat_o; wire [3:0] timerd_ctrl_o; +wire [7:0] timerd_set_data; mfp_timer timer_d ( .CLK (clk), @@ -176,7 +183,8 @@ mfp_timer timer_d ( .DAT_I (din), .DAT_O (timerd_dat_o), .DAT_WE ((addr == 5'h12) && write), - .T_O_PULSE (timerd_done) + .T_O_PULSE (timerd_done), + .SET_DATA_OUT (timerd_set_data) ); reg [7:0] aer, ddr, gpip; @@ -207,6 +215,60 @@ mfp_hbit16 irq_pending_index ( // gpip as output to the cpu (ddr bit == 1 -> gpip pin is output) wire [7:0] gpip_cpu_out = (i & ~ddr) | (gpip & ddr); +// assemble output status structure. Adjust bitrate endianess +assign serial_status_out = { + bitrate[7:0], bitrate[15:8], bitrate[23:16], bitrate[31:24], + databits, parity, stopbits, input_fifo_status }; + +wire [11:0] timerd_state = { timerd_ctrl_o, timerd_set_data }; + +// Atari RTS: YM-A-4 -> +// Atari CTS: mfp gpio-2 <- + +// --- export bit rate --- +// try to calculate bitrate from timer d config +// bps is 2.457MHz/2/16/prescaler/datavalue +wire [31:0] bitrate = + (uart_ctrl[6] != 1'b1)?32'h80000000: // uart prescaler not 1 + (timerd_state == 12'h101)?32'd19200: // 19200 bit/s + (timerd_state == 12'h102)?32'd9600: // 9600 bit/s + (timerd_state == 12'h104)?32'd4800: // 4800 bit/s + (timerd_state == 12'h105)?32'd3600: // 3600 bit/s (?? isn't that 3840?) + (timerd_state == 12'h108)?32'd2400: // 2400 bit/s + (timerd_state == 12'h10a)?32'd2000: // 2000 bit/s (exact 1920) + (timerd_state == 12'h10b)?32'd1800: // 1800 bit/s (exact 1745) + (timerd_state == 12'h110)?32'd1200: // 1200 bit/s + (timerd_state == 12'h120)?32'd600: // 600 bit/s + (timerd_state == 12'h140)?32'd300: // 300 bit/s + (timerd_state == 12'h160)?32'd200: // 200 bit/s + (timerd_state == 12'h180)?32'd150: // 150 bit/s + (timerd_state == 12'h18f)?32'd134: // 134 bit/s + (timerd_state == 12'h18f)?32'd134: // 134 bit/s (134.27) + (timerd_state == 12'h1af)?32'd110: // 110 bit/s (109.71) + (timerd_state == 12'h240)?32'd75: // 75 bit/s (120) + (timerd_state == 12'h260)?32'd50: // 50 bit/s (80) + 32'h80000001; // unsupported bit rate + +wire [7:0] input_fifo_status = { 5'd0, + serial_data_in_empty, serial_data_in_full, serial_data_in_available }; + +wire [7:0] parity = + (uart_ctrl[1] == 1'b0)?8'h00: // no parity + (uart_ctrl[0] == 1'b0)?8'h01: // odd parity + 8'h02; // even parity + +wire [7:0] stopbits = + (uart_ctrl[3:2] == 2'b00)?8'hff: // sync mode not supported + (uart_ctrl[3:2] == 2'b01)?8'h00: // async 1 stop bit + (uart_ctrl[3:2] == 2'b10)?8'h01: // async 1.5 stop bits + 8'h11; // async 2 stop bits + +wire [7:0] databits = + (uart_ctrl[5:4] == 2'b00)?8'd8: // 8 data bits + (uart_ctrl[5:4] == 2'b01)?8'd7: // 7 data bits + (uart_ctrl[5:4] == 2'b10)?8'd6: // 6 data bits + 8'd5; // 5 data bits + // cpu controllable uart control bits reg [1:0] uart_rx_ctrl; reg [3:0] uart_tx_ctrl; @@ -270,10 +332,19 @@ wire [7:0] gpio_irq = ~aer ^ ((i & ~ti_irq_mask) | (ti_irq & ti_irq_mask)); wire [15:0] ipr; reg [15:0] ipr_reset; +// the cpu reading data clears rx irq. It may raise again immediately if there's more +// data in the input fifo. Use a delayed cpu read signal to make sure the fifo finishes +// removing the byte before +wire uart_rx_irq = serial_data_in_available && !serial_cpu_data_readD; + +// the io controller reading data clears tx irq. It may raus again immediately if +// there's more data in the output fifo +wire uart_tx_irq = !serial_data_out_fifo_full && !serial_strobe_out; + // map the 16 interrupt sources onto the 16 interrupt register bits wire [15:0] ipr_set = { - gpio_irq[7:6], timera_done, serial_data_in_available, - 1'b0 /* rcv err */, !serial_data_out_fifo_full, 1'b0 /* tx err */, timerb_done, + gpio_irq[7:6], timera_done, uart_rx_irq, + 1'b0 /* rcv err */, uart_tx_irq, 1'b0 /* tx err */, timerb_done, gpio_irq[5:4], timerc_done, timerd_done, gpio_irq[3:0] }; diff --git a/cores/mist/mfp_timer.v b/cores/mist/mfp_timer.v index 0c0a67a..717a047 100644 --- a/cores/mist/mfp_timer.v +++ b/cores/mist/mfp_timer.v @@ -39,9 +39,15 @@ module mfp_timer( output PULSE_MODE, // pulse mode disables input port irq output reg T_O, - output reg T_O_PULSE + output reg T_O_PULSE, + + // current data bits are exported to allow mfp some rs232 bitrate + // calculations + output [7:0] SET_DATA_OUT ); +assign SET_DATA_OUT = data; + reg [7:0] data, down_counter, cur_counter; reg [3:0] control; diff --git a/cores/mist/mist_top.v b/cores/mist/mist_top.v index db39a18..36bae0c 100644 --- a/cores/mist/mist_top.v +++ b/cores/mist/mist_top.v @@ -1,7 +1,7 @@ /********************************************/ /* */ /********************************************/ - + module mist_top ( // clock inputs input wire [ 2-1:0] CLOCK_27, // 27 MHz @@ -365,7 +365,7 @@ wire mfp_io7 = system_ctrl[8] ^ (ste?ste_dma_snd_xsirq:1'b0); wire parallel_fifo_full; wire mfp_io0 = (usb_redirection == 2'd2)?parallel_fifo_full:~joy0[4]; -// inputs 1,2 and 6 are inputs from serial which have pullups before an inverter +// inputs 1,2 and 6 are inputs from serial which have pullups before and inverter wire [7:0] mfp_gpio_in = {mfp_io7, 1'b0, !dma_irq, !acia_irq, !blitter_irq, 2'b00, mfp_io0}; wire [1:0] mfp_timer_in = {!st_de, ste?ste_dma_snd_xsirq_delayed:!parallel_fifo_full}; @@ -386,8 +386,10 @@ mfp mfp ( .serial_data_out_available (serial_data_from_mfp_available), .serial_strobe_out (serial_strobe_from_mfp), .serial_data_out (serial_data_from_mfp), + .serial_status_out (serial_status_from_mfp), .serial_strobe_in (serial_strobe_to_mfp), .serial_data_in (serial_data_to_mfp), + .serial_status_in (serial_status_to_mfp), // input signals .clk_ext (clk_mfp ), // 2.457MHz clock @@ -1102,6 +1104,8 @@ wire serial_strobe_from_mfp; wire serial_data_from_mfp_available; wire [7:0] serial_data_to_mfp; wire serial_strobe_to_mfp; +wire [7:0] serial_status_to_mfp; +wire [63:0] serial_status_from_mfp; // connection to transfer parallel data from psg to io controller wire [7:0] parallel_data_out; @@ -1147,8 +1151,10 @@ user_io user_io( .serial_strobe_out (serial_strobe_from_mfp), .serial_data_out (serial_data_from_mfp), .serial_data_out_available (serial_data_from_mfp_available), + .serial_status_out (serial_status_from_mfp), .serial_strobe_in (serial_strobe_to_mfp), .serial_data_in (serial_data_to_mfp), + .serial_status_in (serial_status_to_mfp), // parallel interface .parallel_strobe_out (parallel_strobe_out), diff --git a/cores/mist/user_io.v b/cores/mist/user_io.v index 9539f51..d175acf 100644 --- a/cores/mist/user_io.v +++ b/cores/mist/user_io.v @@ -21,11 +21,15 @@ module user_io( output reg serial_strobe_out, input serial_data_out_available, input [7:0] serial_data_out, + // serial status from mfp to io controller + input [63:0] serial_status_out, // serial data from io controller to mfp output reg serial_strobe_in, output reg [7:0] serial_data_in, - + // serial status from io controller to mfp + output reg [7:0] serial_status_in, + // parallel data from psg/ym to io controller output reg parallel_strobe_out, input parallel_data_out_available, @@ -62,7 +66,7 @@ module user_io( wire [7:0] spi_sck_D = { spi_sck_D[6:0], SPI_CLK } /* synthesis keep */; wire spi_sck = (spi_sck && spi_sck_D != 8'h00) || (!spi_sck && spi_sck_D == 8'hff); -reg [1:0] byte_cnt; +reg [3:0] byte_cnt; reg [6:0] sbuf; reg [7:0] cmd; reg [3:0] bit_cnt; // 0..15 @@ -74,7 +78,11 @@ wire [2:0] tx_bit = ~(bit_cnt[2:0]); assign BUTTONS = but_sw[1:0]; assign SWITCHES = but_sw[3:2]; assign scandoubler_disable = but_sw[4]; - + +// prepent "a5" to status to make sure io controller can detect that a core +// doesn't support the command +wire [63+8:0] serial_status_out_x = { 8'ha5, serial_status_out }; + always@(negedge spi_sck) begin if(bit_cnt <= 7) SPI_MISO <= CORE_TYPE[7-bit_cnt]; @@ -113,18 +121,22 @@ always@(negedge spi_sck) begin // ethernet status if(cmd == 8'h0a) - SPI_MISO <= eth_status[{~byte_cnt, tx_bit}]; + SPI_MISO <= eth_status[{~byte_cnt[1:0], tx_bit}]; // read ethernet tx buffer if(cmd == 8'h0b) SPI_MISO <= eth_tx_read_byte[tx_bit]; + + // serial status + if(cmd == 8'h0d) + SPI_MISO <= serial_status_out_x[{4'h8-byte_cnt, tx_bit}]; end end always@(posedge spi_sck, posedge SPI_SS_IO) begin if(SPI_SS_IO == 1) begin bit_cnt <= 4'd0; - byte_cnt <= 2'd0; + byte_cnt <= 4'd0; // ikbd (kbd, joysticks, mouse) ikbd_strobe_in <= 1'b0; @@ -152,7 +164,7 @@ always@(negedge spi_sck) begin bit_cnt <= bit_cnt + 4'd1; else begin bit_cnt <= 4'd8; - byte_cnt <= byte_cnt + 2'd1; + byte_cnt <= byte_cnt + 4'd1; end // command byte finished @@ -236,9 +248,12 @@ always@(negedge spi_sck) begin if(cmd == 8'h0c) begin eth_rx_write_byte <= { sbuf, SPI_MOSI }; eth_rx_write_strobe <= 1'b1; -// eth_rx_write_begin <= 1'b1; end + // serial_status from io controller + if((cmd == 8'h0d) && (byte_cnt == 1)) + serial_status_in <= { sbuf, SPI_MOSI }; + // four extra joysticks ... if(cmd == 8'h10) joy0 <= { sbuf[4:0], SPI_MOSI };