mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-01-28 04:37:12 +00:00
[QL] qimi mouse support
This commit is contained in:
@@ -24,6 +24,8 @@ module mdv (
|
||||
input clk, // 21mhz clock
|
||||
input reset,
|
||||
|
||||
input reverse,
|
||||
|
||||
input sel,
|
||||
|
||||
// control bits
|
||||
@@ -60,8 +62,6 @@ assign tx_empty = 1'b0;
|
||||
// the part of ram which is unavailable to the 68k CPU (>16MB). It is then continously
|
||||
// replayed from there at 200kbit/s
|
||||
|
||||
reg [7:0] mdv_sector /* synthesis noprune */;
|
||||
|
||||
reg [24:0] mdv_end /* synthesis noprune */;
|
||||
|
||||
// determine mdv image size after download
|
||||
@@ -134,7 +134,6 @@ always @(posedge mdv_clk) begin
|
||||
mdv_gap_cnt <= 10'd0; // count bytes until gap
|
||||
mdv_gap_state <= 1'b1; // toggle header + data gap
|
||||
mdv_gap_active <= 1'b1; // gap atm
|
||||
mdv_sector <= 8'd0;
|
||||
mdv_gap <= 1'b1;
|
||||
end else begin
|
||||
mdv_gap_cnt <= mdv_gap_cnt + 10'd1;
|
||||
@@ -162,18 +161,17 @@ always @(posedge mdv_clk) begin
|
||||
mdv_gap_active <= 1'b1; // now comes a gap
|
||||
mdv_gap <= 1'b1;
|
||||
|
||||
// The sectors on cartridges are written in descending order
|
||||
// The images seem to contain them in ascending order. So we
|
||||
// have to replay them backwards for better performance
|
||||
if(reverse) begin
|
||||
// The sectors on cartridges are written in descending order
|
||||
// Some images seem to contain them in ascending order. So we
|
||||
// have to replay them backwards for better performance
|
||||
|
||||
if(mem_addr == BASE_ADDR + 343 - 1)
|
||||
mem_addr <= mdv_end - 343 + 1;
|
||||
else
|
||||
mem_addr <= mem_addr - 2*343 + 1;
|
||||
|
||||
mdv_sector <= mdv_sector + 8'd1;
|
||||
if(mem_addr == BASE_ADDR + 343 - 1)
|
||||
mem_addr <= mdv_end - 343 + 1;
|
||||
else
|
||||
mem_addr <= mem_addr - 2*343 + 1;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
150
cores/ql/qimi.v
Normal file
150
cores/ql/qimi.v
Normal file
@@ -0,0 +1,150 @@
|
||||
//
|
||||
// qimi.v - Ql mouse Interface
|
||||
//
|
||||
// Sinclair QL for the MiST
|
||||
// https://github.com/mist-devel
|
||||
//
|
||||
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
|
||||
//
|
||||
// This source file is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
module qimi (
|
||||
input clk,
|
||||
input reset,
|
||||
|
||||
input cpu_sel,
|
||||
input [1:0] cpu_addr, // a5, a1
|
||||
output [7:0] cpu_data,
|
||||
output reg irq,
|
||||
|
||||
// ps2 interface
|
||||
input ps2_clk,
|
||||
input ps2_data
|
||||
);
|
||||
|
||||
// generate irq ack whenever cpu accesses 1bf9c
|
||||
reg irq_ack;
|
||||
always @(negedge clk) begin
|
||||
irq_ack <= 1'b0;
|
||||
if(cpu_sel && cpu_addr == 2'b11)
|
||||
irq_ack <= 1'b1;
|
||||
end
|
||||
|
||||
wire x_dir = !x_pos[9];
|
||||
wire y_dir = !y_pos[9];
|
||||
wire x_mov = (x_pos != 0);
|
||||
wire y_mov = (y_pos != 0);
|
||||
|
||||
assign cpu_data =
|
||||
(cpu_addr == 2'b00)?{2'b00,!b[0],!b[1],4'b0000}: // 1bf9c
|
||||
(cpu_addr == 2'b10)?{2'b00,y_mov,x_dir,1'b0,x_mov,1'b0,y_dir }: // 1bfbc
|
||||
8'h00;
|
||||
|
||||
// registers keeping state of current mouse state
|
||||
reg [1:0] b;
|
||||
reg [9:0] x_pos;
|
||||
reg [9:0] y_pos;
|
||||
|
||||
wire [7:0] byte;
|
||||
wire valid;
|
||||
wire error;
|
||||
|
||||
reg [1:0] cnt;
|
||||
|
||||
reg sign_x, sign_y;
|
||||
reg [7:0] x_reg;
|
||||
|
||||
// counter to limit irq rate to 2khz
|
||||
reg [9:0] irq_holdoff;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(reset) begin
|
||||
x_pos <= 10'd0;
|
||||
y_pos <= 10'd0;
|
||||
cnt <= 2'd0;
|
||||
irq <= 1'b0;
|
||||
irq_holdoff <= 10'd0;
|
||||
end else begin
|
||||
// check if we have to fire another irq
|
||||
if(irq_holdoff != 0) begin
|
||||
irq_holdoff <= irq_holdoff - 10'd1;
|
||||
if((irq_holdoff == 1) && (x_mov || y_mov))
|
||||
irq <= 1'b1;
|
||||
end
|
||||
|
||||
// ps2 decoder has received a valid byte
|
||||
if(valid) begin
|
||||
// count through all three data bytes
|
||||
cnt <= cnt + 2'd1;
|
||||
|
||||
if(cnt == 0) begin
|
||||
// bit 3 must be 1. Stay in state 0 otherwise
|
||||
if(!byte[3]) cnt <= 2'd0;
|
||||
b <= byte[1:0];
|
||||
sign_x <= byte[4];
|
||||
sign_y <= byte[5];
|
||||
end else if(cnt == 1) begin
|
||||
x_reg <= byte;
|
||||
end else begin
|
||||
// the ps2 packet contains a 9 bit value. We only use the upper
|
||||
// 7. Otherwise the mouse would be too fast for our low resolution
|
||||
x_pos <= x_pos + { {2{sign_x}}, x_reg};
|
||||
y_pos <= y_pos + { {2{sign_y}}, byte};
|
||||
cnt <= 2'd0;
|
||||
|
||||
if(irq_holdoff == 0)
|
||||
irq_holdoff <= 10'd1;
|
||||
end
|
||||
end else begin
|
||||
// one bit has been reported to host
|
||||
if(irq_ack) begin
|
||||
if(x_pos != 0) begin
|
||||
if(x_pos[9]) x_pos <= x_pos + 10'd1;
|
||||
else x_pos <= x_pos - 10'd1;
|
||||
end
|
||||
|
||||
if(y_pos != 0) begin
|
||||
if(y_pos[9]) y_pos <= y_pos + 10'd1;
|
||||
else y_pos <= y_pos - 10'd1;
|
||||
end
|
||||
|
||||
// clear irq
|
||||
irq <= 1'b0;
|
||||
|
||||
// next irq after some time ...
|
||||
irq_holdoff <= 10'd1000;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// the ps2 decoder has been taken from the zx spectrum core
|
||||
ps2_intf ps2_mouse (
|
||||
.CLK ( clk ),
|
||||
.nRESET ( !reset ),
|
||||
|
||||
// PS/2 interface
|
||||
.PS2_CLK ( ps2_clk ),
|
||||
.PS2_DATA ( ps2_data ),
|
||||
|
||||
// Byte-wide data interface - only valid for one clock
|
||||
// so must be latched externally if required
|
||||
.DATA ( byte ),
|
||||
.VALID ( valid ),
|
||||
.ERROR ( error )
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -155,6 +155,7 @@ set_global_assignment -name FITTER_EFFORT "FAST FIT"
|
||||
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
|
||||
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_*
|
||||
set_global_assignment -name VERILOG_FILE qimi.v
|
||||
set_global_assignment -name VHDL_FILE "t49_rom-struct-a.vhd"
|
||||
set_global_assignment -name VHDL_FILE "t48/rtl/vhdl/system/t49_rom-e.vhd"
|
||||
set_global_assignment -name VHDL_FILE t48/rtl/vhdl/system/generic_ram_ena.vhd
|
||||
|
||||
@@ -62,13 +62,14 @@ module ql (
|
||||
parameter CONF_STR = {
|
||||
"QL;;",
|
||||
"F1,MDV;",
|
||||
"O2,RAM,128k,640k;",
|
||||
"O3,Video mode,PAL,NTSC;",
|
||||
"O4,Scanlines,Off,On;",
|
||||
"T5,Reset"
|
||||
"O2,MDV direction,normal,reverse;",
|
||||
"O3,RAM,128k,640k;",
|
||||
"O4,Video mode,PAL,NTSC;",
|
||||
"O5,Scanlines,Off,On;",
|
||||
"T6,Reset"
|
||||
};
|
||||
|
||||
parameter CONF_STR_LEN = 4+7+17+23+20+8;
|
||||
parameter CONF_STR_LEN = 4+7+32+17+23+20+8;
|
||||
|
||||
// the status register is controlled by the on screen display (OSD)
|
||||
wire [7:0] status;
|
||||
@@ -78,6 +79,7 @@ wire [1:0] buttons;
|
||||
wire [7:0] js0, js1;
|
||||
|
||||
wire ps2_kbd_clk, ps2_kbd_data;
|
||||
wire ps2_mouse_clk, ps2_mouse_data;
|
||||
|
||||
// generate ps2_clock
|
||||
wire ps2_clock = ps2_clk_div[6]; // ~20khz
|
||||
@@ -104,6 +106,8 @@ user_io #(.STRLEN(CONF_STR_LEN)) user_io (
|
||||
.ps2_clk ( ps2_clock ),
|
||||
.ps2_kbd_clk ( ps2_kbd_clk ),
|
||||
.ps2_kbd_data ( ps2_kbd_data ),
|
||||
.ps2_mouse_clk ( ps2_mouse_clk ),
|
||||
.ps2_mouse_data ( ps2_mouse_data ),
|
||||
|
||||
.status ( status )
|
||||
);
|
||||
@@ -242,9 +246,9 @@ zx8301 zx8301 (
|
||||
.clk_video ( clk10 ),
|
||||
.video_cycle ( video_cycle ),
|
||||
|
||||
.ntsc ( status[3] ),
|
||||
.ntsc ( status[4] ),
|
||||
.scandoubler ( !tv15khz ),
|
||||
.scanlines ( status[4] ),
|
||||
.scanlines ( status[5] ),
|
||||
|
||||
.clk_bus ( clk2 ),
|
||||
.cpu_cs ( zx8301_cs ),
|
||||
@@ -271,7 +275,7 @@ wire rom_download = dio_download && (dio_index == 0);
|
||||
reg [11:0] reset_cnt;
|
||||
wire reset = (reset_cnt != 0);
|
||||
always @(posedge clk2) begin
|
||||
if(buttons[1] || status[0] || status[5] || !pll_locked || rom_download)
|
||||
if(buttons[1] || status[0] || status[6] || !pll_locked || rom_download)
|
||||
reset_cnt <= 12'hfff;
|
||||
else if(reset_cnt != 0)
|
||||
reset_cnt <= reset_cnt - 1;
|
||||
@@ -300,12 +304,13 @@ zx8302 zx8302 (
|
||||
.clk_sys ( CLOCK_27[0] ),
|
||||
.clk ( clk21 ),
|
||||
|
||||
.xint ( qimi_irq ),
|
||||
.ipl ( cpu_ipl ),
|
||||
.led ( LED ),
|
||||
.audio ( audio ),
|
||||
|
||||
// CPU connection
|
||||
.clk_bus ( clk2 ),
|
||||
.clk_bus ( clk2 ),
|
||||
.cpu_sel ( zx8302_sel ),
|
||||
.cpu_wr ( cpu_wr ),
|
||||
.cpu_addr ( zx8302_addr ),
|
||||
@@ -329,11 +334,35 @@ zx8302 zx8302 (
|
||||
.mdv_men ( mdv_men ),
|
||||
.video_cycle ( video_cycle ),
|
||||
|
||||
.mdv_reverse ( status[2] ),
|
||||
|
||||
.mdv_download ( mdv_download ),
|
||||
.mdv_dl_addr ( dio_addr )
|
||||
|
||||
);
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// --------------------------- QIMI compatible mouse -------------------------------
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
// qimi is at 1bfxx
|
||||
wire qimi_sel = cpu_io && (cpu_addr[13:8] == 6'b111111);
|
||||
wire [7:0] qimi_data;
|
||||
wire qimi_irq;
|
||||
|
||||
qimi qimi(
|
||||
.reset ( reset ),
|
||||
.clk ( clk2 ),
|
||||
|
||||
.cpu_sel ( qimi_sel ),
|
||||
.cpu_addr ( { cpu_addr[5], cpu_addr[1] } ),
|
||||
.cpu_data ( qimi_data ),
|
||||
.irq ( qimi_irq ),
|
||||
|
||||
.ps2_clk ( ps2_mouse_clk ),
|
||||
.ps2_data ( ps2_mouse_data )
|
||||
);
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// -------------------------------------- CPU --------------------------------------
|
||||
// ---------------------------------------------------------------------------------
|
||||
@@ -341,13 +370,16 @@ zx8302 zx8302 (
|
||||
// address decoding
|
||||
wire cpu_io = ({cpu_addr[19:14], 2'b00} == 8'h18); // internal IO $18000-$1bffff
|
||||
wire cpu_bram = (cpu_addr[19:17] == 3'b001); // 128k RAM at $20000
|
||||
wire cpu_xram = status[2] && ((cpu_addr[19:18] == 2'b01) ||
|
||||
wire cpu_xram = status[3] && ((cpu_addr[19:18] == 2'b01) ||
|
||||
(cpu_addr[19:18] == 2'b10)); // 512k RAM at $40000 if enabled
|
||||
wire cpu_ram = cpu_bram || cpu_xram; // any RAM
|
||||
wire cpu_rom = (cpu_addr[19:16] == 4'h0); // 64k ROM at $0
|
||||
wire cpu_mem = cpu_ram || cpu_rom; // any memory mapped to sdram
|
||||
|
||||
wire [15:0] io_dout = cpu_addr[6]?16'h0000:zx8302_dout;
|
||||
wire [15:0] io_dout =
|
||||
qimi_sel?{qimi_data, qimi_data}:
|
||||
(!cpu_addr[6])?zx8302_dout:
|
||||
16'h0000;
|
||||
|
||||
// demultiplex the various data sources
|
||||
wire [15:0] cpu_din =
|
||||
|
||||
@@ -3,4 +3,23 @@ QL for MIST
|
||||
|
||||
This is an implementation of the Sinclair QL for the MIST board.
|
||||
|
||||
It's based on the TG68K CPU core.
|
||||
It's based on the TG68K CPU core and the t48 core for the IPC.
|
||||
|
||||
Features:
|
||||
- tg68k
|
||||
- 128k or 640k
|
||||
- roughly twice the original speed
|
||||
- zx8301
|
||||
- all video modes incl. blinking
|
||||
- scan doubler for VGA output (can be disabled)
|
||||
- optional scan line effect
|
||||
- zx8302
|
||||
- IPC based on t48 using the original firmware
|
||||
- audio
|
||||
- keyboard
|
||||
- PC keyboard shortcuts (backspace, ...)
|
||||
- joysticks
|
||||
- interrupt handling
|
||||
- microdrive emulation
|
||||
- qlay format
|
||||
- qimi mouse
|
||||
|
||||
@@ -28,7 +28,8 @@ module zx8302 (
|
||||
|
||||
// interrupts
|
||||
output [1:0] ipl,
|
||||
|
||||
input xint,
|
||||
|
||||
// sdram interface for microdrive emulation
|
||||
output [24:0] mdv_addr,
|
||||
input [15:0] mdv_din,
|
||||
@@ -39,7 +40,8 @@ module zx8302 (
|
||||
// interface to watch MDV cartridge upload
|
||||
input [24:0] mdv_dl_addr,
|
||||
input mdv_download,
|
||||
|
||||
|
||||
input mdv_reverse,
|
||||
output led,
|
||||
output audio,
|
||||
|
||||
@@ -129,8 +131,8 @@ wire [7:0] io_status = { zx8302_comdata_in, ipc_busy, 2'b00,
|
||||
|
||||
assign cpu_dout =
|
||||
// 18000/18001 and 18002/18003
|
||||
(cpu_addr == 2'b00)?rtc[46:31]:
|
||||
(cpu_addr == 2'b01)?rtc[30:15]:
|
||||
(cpu_addr == 2'b00)?rtc[47:32]:
|
||||
(cpu_addr == 2'b01)?rtc[31:16]:
|
||||
|
||||
// 18020/18021 and 18022/18023
|
||||
(cpu_addr == 2'b10)?{io_status, irq_pending}:
|
||||
@@ -195,7 +197,7 @@ ipc ipc (
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
wire [7:0] irq_pending = {1'b0, (mdv_sel == 0), clk64k,
|
||||
1'b0, vsync_irq, 1'b0, 1'b0, gap_irq };
|
||||
xint_irq, vsync_irq, 1'b0, 1'b0, gap_irq };
|
||||
reg [2:0] irq_mask;
|
||||
reg [4:0] irq_ack;
|
||||
|
||||
@@ -219,6 +221,14 @@ always @(posedge gap_irq_in or posedge gap_irq_reset) begin
|
||||
else gap_irq <= 1'b1;
|
||||
end
|
||||
|
||||
// toggling the mask will also trigger irqs ...
|
||||
wire xint_irq_in = xint && irq_mask[2];
|
||||
reg xint_irq;
|
||||
wire xint_irq_reset = reset || irq_ack[4];
|
||||
always @(posedge xint_irq_in or posedge xint_irq_reset) begin
|
||||
if(xint_irq_reset) xint_irq <= 1'b0;
|
||||
else xint_irq <= 1'b1;
|
||||
end
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
@@ -233,11 +243,13 @@ wire [7:0] mdv_byte;
|
||||
assign led = !mdv_sel[0];
|
||||
|
||||
mdv mdv (
|
||||
.clk ( clk ),
|
||||
.clk ( clk ),
|
||||
.reset ( init ),
|
||||
|
||||
.sel ( mdv_sel[0] ),
|
||||
|
||||
.reverse ( mdv_reverse ),
|
||||
|
||||
// control bits
|
||||
.gap ( mdv_gap ),
|
||||
.tx_empty ( mdv_tx_empty ),
|
||||
@@ -267,9 +279,9 @@ always @(negedge mctrl[1])
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
// PLL for the real time clock (rtc)
|
||||
reg [46:0] rtc;
|
||||
reg [47:0] rtc;
|
||||
always @(posedge clk64k)
|
||||
rtc <= rtc + 47'd1;
|
||||
rtc <= rtc + 48'd1;
|
||||
|
||||
wire clk64k;
|
||||
pll_rtc pll_rtc (
|
||||
|
||||
Reference in New Issue
Block a user