Revision 374
Added by markw over 10 years ago
| common/a8core/sio_device.vhdl | ||
|---|---|---|
| 
     	constant state_wait_high_low : std_logic_vector(3 downto 0) := "0000";
 
   | 
||
| 
     	constant state_command_clear_irq : std_logic_vector(3 downto 0) := "0001";
 
   | 
||
| 
     	constant state_command_enable_irq : std_logic_vector(3 downto 0) := "0010";
 
   | 
||
| 
     	constant state_command_wait_for_byte : std_logic_vector(3 downto 0) := "0011";
 
   | 
||
| 
     	constant state_command_clear_irq2 : std_logic_vector(3 downto 0) := "0100";
 
   | 
||
| 
     	constant state_command_enable_irq2 : std_logic_vector(3 downto 0) := "0101";
 
   | 
||
| 
     	constant state_command_read_data : std_logic_vector(3 downto 0) := "0110";
 
   | 
||
| 
     	constant state_command_ready_on_command_high : std_logic_vector(3 downto 0) := "0111";
 
   | 
||
| 
     	constant state_command_reset_skstat : std_logic_vector(3 downto 0) := "1011";
 
   | 
||
| 
     	constant state_command_wait_for_byte : std_logic_vector(3 downto 0) := "0100";
 
   | 
||
| 
     	constant state_command_clear_irq2 : std_logic_vector(3 downto 0) := "0101";
 
   | 
||
| 
     	constant state_command_enable_irq2 : std_logic_vector(3 downto 0) := "0110";
 
   | 
||
| 
     	constant state_command_read_data : std_logic_vector(3 downto 0) := "0111";
 
   | 
||
| 
     	constant state_command_ready : std_logic_vector(3 downto 0) := "1000";
 
   | 
||
| 
     	constant state_command_error : std_logic_vector(3 downto 0) := "1001";
 
   | 
||
| 
     	constant state_command_stop : std_logic_vector(3 downto 0) := "1111";
 
   | 
||
| 
     	signal clear_request : std_logic;
 
   | 
||
| 
     | 
||
| 
     	signal state_wr_en : std_logic;
 
   | 
||
| ... | ... | |
| 
     | 
||
| 
     	signal pokey_data_out : std_logic_vector(7 downto 0);
 
   | 
||
| 
     | 
||
| 
     	constant pokey_skrest : std_logic_vector(3 downto 0) := x"a";
 
   | 
||
| 
     	constant pokey_serout : std_logic_vector(3 downto 0) := x"d";
 
   | 
||
| 
     	constant pokey_irqen : std_logic_vector(3 downto 0) := x"e";
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     	process(clk,reset_n)
 
   | 
||
| 
     	begin
 
   | 
||
| 
     		if (reset_n = '0') then
 
   | 
||
| 
     			state_reg <= state_wait_high_low;	
 
   | 
||
| 
     			-- wait for explicit initialisation via clear
 
   | 
||
| 
     			state_reg <= state_command_stop;
 
   | 
||
| 
     			target_reg <= (others=>'0');
 
   | 
||
| 
     			command_reg <= '1';	
 
   | 
||
| 
     			en_delay_reg <= (others=>'0');
 
   | 
||
| ... | ... | |
| 
     				if (state_reg = state_command_ready) then
 
   | 
||
| 
     					data_out(0) <= '1';
 
   | 
||
| 
     				end if;
 
   | 
||
| 
     				if (state_reg = state_command_stop) then
 
   | 
||
| 
     					data_out(6) <= '1';
 
   | 
||
| 
     				end if;
 
   | 
||
| 
     				if (state_reg = state_command_error) then
 
   | 
||
| 
     					data_out(7) <= '1';
 
   | 
||
| 
     				end if;
 
   | 
||
| 
     			end if;
 
   | 
||
| 
     		else
 
   | 
||
| 
     			data_out <= pokey_data_out;
 
   | 
||
| ... | ... | |
| 
     	end process;
 
   | 
||
| 
     | 
||
| 
     	-- state machine
 
   | 
||
| 
     	process(state_reg, command_next, command_reg, bus_free, pokey_data_out, target_reg, clear_request, sio_command)
 
   | 
||
| 
     	process(state_reg, command_reg, bus_free, pokey_data_out, target_reg, clear_request, sio_command)
 
   | 
||
| 
     	begin
 
   | 
||
| 
     		state_next <= state_reg;
 
   | 
||
| 
     		state_wr_en <= '0';
 
   | 
||
| ... | ... | |
| 
     				state_addr<=pokey_irqen;
 
   | 
||
| 
     				state_wr_en<='1';
 
   | 
||
| 
     				state_data<=x"38";
 
   | 
||
| 
     				state_next <= state_command_wait_for_byte;				
 
   | 
||
| 
     				state_next <= state_command_reset_skstat;
 
   | 
||
| 
     			when state_command_reset_skstat =>
 
   | 
||
| 
     				state_addr<=pokey_skrest;
 
   | 
||
| 
     				state_wr_en<='1';
 
   | 
||
| 
     				state_data<=x"00";
 
   | 
||
| 
     				state_next <= state_command_wait_for_byte;
 
   | 
||
| 
     			when state_command_wait_for_byte =>
 
   | 
||
| 
     				state_addr<=pokey_irqen;
 
   | 
||
| 
     				if (pokey_data_out(5)='0') then
 
   | 
||
| 
     					state_next <= state_command_clear_irq2;
 
   | 
||
| 
     				else
 
   | 
||
| 
     					if (sio_command = '1') then
 
   | 
||
| 
     						if (target_reg="101") then
 
   | 
||
| 
     							state_next <= state_command_ready;
 
   | 
||
| 
     						else
 
   | 
||
| 
     							state_next <= state_command_error;
 
   | 
||
| 
     						end if;
 
   | 
||
| 
     					end if;
 
   | 
||
| 
     				end if;
 
   | 
||
| 
     			when state_command_clear_irq2 =>
 
   | 
||
| 
     				state_addr<=pokey_irqen;
 
   | 
||
| ... | ... | |
| 
     				state_addr<=pokey_irqen;
 
   | 
||
| 
     				state_wr_en<='1';
 
   | 
||
| 
     				state_data<=x"38";
 
   | 
||
| 
     				state_next <= state_command_read_data;								
 
   | 
||
| 
     				state_next <= state_command_read_data;
 
   | 
||
| 
     			when state_command_read_data =>
 
   | 
||
| 
     				state_addr<=pokey_serout;
 
   | 
||
| 
     				target_wr_en<='1';
 
   | 
||
| 
     				if (target_reg="100") then
 
   | 
||
| 
     					state_next <= state_command_ready_on_command_high;
 
   | 
||
| 
     				else
 
   | 
||
| 
     					state_next <= state_command_wait_for_byte;
 
   | 
||
| 
     				state_next <= state_command_wait_for_byte;
 
   | 
||
| 
     				case target_reg is
 
   | 
||
| 
     				when "000"|"001"|"010"|"011"|"100" =>
 
   | 
||
| 
     					target_next <= std_logic_vector(unsigned(target_reg)+1);
 
   | 
||
| 
     					target_wr_en<='1';
 
   | 
||
| 
     				when others =>
 
   | 
||
| 
     					-- indicate error, too many command bytes
 
   | 
||
| 
     					target_next <= "111";
 
   | 
||
| 
     				end case;
 
   | 
||
| 
     			when state_command_ready =>
 
   | 
||
| 
     				if (sio_command = '0') then
 
   | 
||
| 
     					-- invalidate command frame when command goes low
 
   | 
||
| 
     					state_next <= state_command_error;
 
   | 
||
| 
     				end if;
 
   | 
||
| 
     			when state_command_ready_on_command_high =>
 
   | 
||
| 
     				if (command_reg='1') then
 
   | 
||
| 
     					state_next <= state_command_ready;
 
   | 
||
| 
     				end if;
 
   | 
||
| 
     			when state_command_ready =>
 
   | 
||
| 
     			when state_command_error => null;
 
   | 
||
| 
     			when state_command_stop => null;
 
   | 
||
| 
     			when others =>
 
   | 
||
| 
     				state_next <= state_wait_high_low;
 
   | 
||
| 
     				state_next <= state_command_stop;
 
   | 
||
| 
     			end case;
 
   | 
||
| 
     		end if;
 
   | 
||
| 
     | 
||
| de1/atari800core_de1.vhd | ||
|---|---|---|
| 
     		 );
 
   | 
||
| 
     | 
||
| 
     -- PIA mapping
 
   | 
||
| 
     SIO_COMMAND <= CB2_OUT;
 
   | 
||
| 
     -- emulate pull-up on command line
 
   | 
||
| 
     SIO_COMMAND <= CB2_OUT when CB2_DIR_OUT='1' else '1';
 
   | 
||
| 
     -- SIO_COMMAND <= CB2_OUT;
 
   | 
||
| 
     --PORTA_IN <= ((JOY2_n(3)&JOY2_n(2)&JOY2_n(1)&JOY2_n(0)&JOY1_n(3)&JOY1_n(2)&JOY1_n(1)&JOY1_n(0)) and not (porta_dir_out)) or (porta_dir_out and porta_out);
 
   | 
||
| 
     --PORTA_IN <= (not (porta_dir_out)) or (porta_dir_out and porta_out);
 
   | 
||
| 
     PORTB_IN <= PORTB_OUT;
 
   | 
||
| de1/gpiov2.vhd | ||
|---|---|---|
| 
     -- OUTPUTS TO GPIO
 
   | 
||
| 
     	-- unused
 
   | 
||
| 
     	--GPIO_0_DIR_OUT(35 downto 4) <= (others=>'0');
 
   | 
||
| 
     	GPIO_0_OUT(35 downto 0) <= (others=>'0');
 
   | 
||
| 
     | 
||
| 
     	GPIO_0_OUT(35 downto 2) <= (others=>'0');
 
   | 
||
| 
     	GPIO_0_OUT(1) <= '0' when gpio_enable='1' else CB2_OUT;
 
   | 
||
| 
     	GPIO_0_OUT(0) <= '0';
 
   | 
||
| 
     | 
||
| 
     	-- sio
 
   | 
||
| 
     	--CB1=SIO_IRQ
 
   | 
||
| 
     	--CB2=SIO_COMMAND
 
   | 
||
| ... | ... | |
| 
     	--CA2=SIO_MOTOR_RAW
 
   | 
||
| 
     | 
||
| 
     	GPIO_0_DIR_OUT(0) <= '0';
 
   | 
||
| 
     	GPIO_0_DIR_OUT(1) <= CB2_dir_out and not(CB2_OUT) and gpio_enable;
 
   | 
||
| 
     	GPIO_0_DIR_OUT(1) <= CB2_dir_out and not(CB2_OUT) when gpio_enable='1' else '1';
 
   | 
||
| 
     	GPIO_0_DIR_OUT(2) <= '0';
 
   | 
||
| 
     	GPIO_0_DIR_OUT(3) <= CA2_dir_out and not(CA2_OUT) and gpio_enable;
 
   | 
||
| 
     	GPIO_0_DIR_OUT(4) <= not(SIO_OUT) and gpio_enable;
 
   | 
||
| ... | ... | |
| 
     	GPIO_0_DIR_OUT(6) <= not(SIO_CLOCKOUT) and gpio_enable;
 
   | 
||
| 
     	GPIO_0_DIR_OUT(7) <= '0';
 
   | 
||
| 
     | 
||
| 
     	CB1_in <= GPIO_0_IN(0);
 
   | 
||
| 
     	CB2_in <= GPIO_0_IN(1);
 
   | 
||
| 
     	CA1_in <= GPIO_0_IN(2);
 
   | 
||
| 
     	CA2_in <= GPIO_0_IN(3);
 
   | 
||
| 
     	SIO_IN <= GPIO_0_IN(5);
 
   | 
||
| 
     	SIO_CLOCKIN <= GPIO_0_IN(7);
 
   | 
||
| 
     	CB1_in <= GPIO_0_IN(0) when gpio_enable='1' else '1';
 
   | 
||
| 
     	CB2_in <= GPIO_0_IN(1) when gpio_enable='1' else '1';
 
   | 
||
| 
     	CA1_in <= GPIO_0_IN(2) when gpio_enable='1' else '1';
 
   | 
||
| 
     	CA2_in <= GPIO_0_IN(3) when gpio_enable='1' else '1';
 
   | 
||
| 
     	SIO_IN <= GPIO_0_IN(5) when gpio_enable='1' else '1';
 
   | 
||
| 
     	SIO_CLOCKIN <= GPIO_0_IN(7) when gpio_enable='1' else '1';
 
   | 
||
| 
     | 
||
| 
     	-- sticks
 
   | 
||
| 
     	-- PORTA7,6,5,4,TRIG1,POT3,2,1,0,PORTA3,2,1,0,TRIG0
 
   | 
||
| firmware/atari_drive_emulator.c | ||
|---|---|---|
| 
     	u08 aux2;
 
   | 
||
| 
     	u08 chksum;
 
   | 
||
| 
     } __attribute__((packed));
 
   | 
||
| 
     | 
||
| 
     static void switch_speed()
 
   | 
||
| 
     {
 
   | 
||
| 
     	if (speed == speedslow)
 
   | 
||
| 
     	{
 
   | 
||
| 
     		speed = speedfast;
 
   | 
||
| 
     	}
 
   | 
||
| 
     	else
 
   | 
||
| 
     	{
 
   | 
||
| 
     		speed = speedslow;
 
   | 
||
| 
     	}
 
   | 
||
| 
     	USART_Init(speed+6);
 
   | 
||
| 
     }
 
   | 
||
| 
     | 
||
| 
     void getCommand(struct command * cmd)
 
   | 
||
| 
     {
 
   | 
||
| 
     	int expchk;
 
   | 
||
| 
     	int i;
 
   | 
||
| 
     | 
||
| 
     	//printf("\n%f:WaitCMD\n",when());
 
   | 
||
| 
     	while (0 == USART_Command_Line());
 
   | 
||
| 
     	//printf("%f:CMDHigh\n",when());
 
   | 
||
| 
     	USART_Init(speed+6);
 
   | 
||
| 
     	//printf("%f:Clear:%d\n",when(),*zpu_siocommand_ready);
 
   | 
||
| 
     	*zpu_siocommand_ready = 1; // clear
 
   | 
||
| 
     | 
||
| 
     	unsigned char cmdstat;
 
   | 
||
| 
     	while (1)
 
   | 
||
| 
     	{
 
   | 
||
| 
     		unsigned char x = *zpu_siocommand_ready;
 
   | 
||
| 
     		if (x != 0) break;
 
   | 
||
| 
     		actions();
 
   | 
||
| 
     		while (0 == USART_Command_Line())
 
   | 
||
| 
     		{
 
   | 
||
| 
     			actions();
 
   | 
||
| 
     			wait_us(3);
 
   | 
||
| 
     		}
 
   | 
||
| 
     		USART_Init(speed+6);
 
   | 
||
| 
     		*zpu_siocommand_ready = 1; // clear
 
   | 
||
| 
     | 
||
| 
     //#ifdef SOCKIT
 
   | 
||
| 
     //		double a = when();
 
   | 
||
| 
     //		while ((when()-a)<3e-6);
 
   | 
||
| 
     //#endif
 
   | 
||
| 
     		wait_us(3);
 
   | 
||
| 
     	} // usb poll can take some ms, but we have 16 ms to reply. We have hardware now to capture the command frame.
 
   | 
||
| 
     	for (i=0;i!=5;++i)
 
   | 
||
| 
     		((unsigned char *)cmd)[i] = zpu_siocommand_data[i<<2];
 
   | 
||
| 
     	*zpu_siocommand_ready = 1; // clear
 
   | 
||
| 
     		do {
 
   | 
||
| 
     			actions();
 
   | 
||
| 
     			wait_us(3);
 
   | 
||
| 
     			cmdstat = *zpu_siocommand_ready;
 
   | 
||
| 
     		} while (0 == cmdstat);
 
   | 
||
| 
     | 
||
| 
     	/*cmd->deviceId = USART_Receive_Byte();
 
   | 
||
| 
     	cmd->command = USART_Receive_Byte();
 
   | 
||
| 
     	cmd->aux1 = USART_Receive_Byte();
 
   | 
||
| 
     	cmd->aux2 = USART_Receive_Byte();
 
   | 
||
| 
     	cmd->chksum = USART_Receive_Byte();*/
 
   | 
||
| 
     	//while (0 == USART_Command_Line());
 
   | 
||
| 
     	//printf("cmd:");
 
   | 
||
| 
     	//printf("Gone high\n");
 
   | 
||
| 
     	atari_sector_buffer[0] = cmd->deviceId;
 
   | 
||
| 
     	atari_sector_buffer[1] = cmd->command;
 
   | 
||
| 
     	atari_sector_buffer[2] = cmd->aux1;
 
   | 
||
| 
     	atari_sector_buffer[3] = cmd->aux2;
 
   | 
||
| 
     	expchk = get_checksum(&atari_sector_buffer[0],4);
 
   | 
||
| 
     		if (cmdstat & 0x40) {
 
   | 
||
| 
     			// state machine is stopped, just (re-)start it
 
   | 
||
| 
     			continue;
 
   | 
||
| 
     		}
 
   | 
||
| 
     		if ((cmdstat & 0x80) || USART_Framing_Error()) {
 
   | 
||
| 
     			// state machine reported error or we got a framing error:
 
   | 
||
| 
     			// switch speed and retry
 
   | 
||
| 
     			switch_speed();
 
   | 
||
| 
     			continue;
 
   | 
||
| 
     		}
 
   | 
||
| 
     		for (i=0;i!=5;++i)
 
   | 
||
| 
     			((unsigned char *)cmd)[i] = zpu_siocommand_data[i<<2];
 
   | 
||
| 
     | 
||
| 
     /*unsigned char * temp = baseaddr;
 
   | 
||
| 
     baseaddr = (unsigned char volatile *)(40000 + atari_regbase);
 
   | 
||
| 
     debug_pos=160;
 
   | 
||
| 
     */
 
   | 
||
| 
     	//printf("%f:CMD: %02x %02x %02x %02x %02x/%02x %s\n",when(),cmd->deviceId,cmd->command,cmd->aux1,cmd->aux2,cmd->chksum,expchk, cmd->chksum!=expchk ? "BAD":"");
 
   | 
||
| 
     /*
 
   | 
||
| 
     baseaddr = temp;*/
 
   | 
||
| 
     		atari_sector_buffer[0] = cmd->deviceId;
 
   | 
||
| 
     		atari_sector_buffer[1] = cmd->command;
 
   | 
||
| 
     		atari_sector_buffer[2] = cmd->aux1;
 
   | 
||
| 
     		atari_sector_buffer[3] = cmd->aux2;
 
   | 
||
| 
     		expchk = get_checksum(&atari_sector_buffer[0],4);
 
   | 
||
| 
     | 
||
| 
     	//printf("Device id:");
 
   | 
||
| 
     	//printf("%d",cmd->deviceId);
 
   | 
||
| 
     	//printf("\n");
 
   | 
||
| 
     	//printf("command:");
 
   | 
||
| 
     	//printf("%d",cmd->command);
 
   | 
||
| 
     	//printf("\n");
 
   | 
||
| 
     	//printf("aux1:");
 
   | 
||
| 
     	//printf("%d",cmd->aux1);
 
   | 
||
| 
     	//printf("\n");
 
   | 
||
| 
     	//printf("aux2:");
 
   | 
||
| 
     	//printf("%d",cmd->aux2);
 
   | 
||
| 
     	//printf("\n");
 
   | 
||
| 
     	//printf("chksum:");
 
   | 
||
| 
     	//printf("%x ",cmd->chksum);
 
   | 
||
| 
     	//printf("%x ",expchk);
 
   | 
||
| 
     | 
||
| 
     	if (expchk!=cmd->chksum || USART_Framing_Error())
 
   | 
||
| 
     	{
 
   | 
||
| 
     		//printf("ERR ");
 
   | 
||
| 
     		//wait_us(1000000);
 
   | 
||
| 
     		if (speed == speedslow)
 
   | 
||
| 
     		{
 
   | 
||
| 
     			speed = speedfast;
 
   | 
||
| 
     			//printf("SPDF");
 
   | 
||
| 
     			//printf("%d",speed);
 
   | 
||
| 
     		if (expchk==cmd->chksum) {
 
   | 
||
| 
     			// got a command frame
 
   | 
||
| 
     			break;
 
   | 
||
| 
     		} else {
 
   | 
||
| 
     			// just an invalid checksum, switch speed anyways
 
   | 
||
| 
     			switch_speed();
 
   | 
||
| 
     		}
 
   | 
||
| 
     		else
 
   | 
||
| 
     		{
 
   | 
||
| 
     			speed = speedslow;
 
   | 
||
| 
     			//printf("SPDS");
 
   | 
||
| 
     			//printf("%d",speed);
 
   | 
||
| 
     		}
 
   | 
||
| 
     	}
 
   | 
||
| 
     	//printf("\n");
 
   | 
||
| 
     | 
||
| 
     	DELAY_T2_MIN;
 
   | 
||
| 
     }
 
   | 
||
| firmware/pokey/uart.c | ||
|---|---|---|
| 
     | 
||
| 
     int USART_Framing_Error()
 
   | 
||
| 
     {
 
   | 
||
| 
     	if (0xc0&(*zpu_pokey_skctl))
 
   | 
||
| 
     	if (0x80&(*zpu_pokey_skctl))
 
   | 
||
| 
     	{
 
   | 
||
| 
     		return 0;
 
   | 
||
| 
     	}
 
   | 
||
Patches to improve SIO from Hias. Many thanks!