English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old Yesterday, 19:52   #21
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 3,432
Quote:
Originally Posted by remz View Post
It is working pretty well now; I would like to share my code here because I love to learn from you about best practices and optimizations.
The trouble is (again) that you do not know whether enough time has passed from writing to INREQ to returning from the interrupt. I mentioned this already. If the CPU is fast enough, the code may *still* return before PAULA had a chance to lower the interrupt. Again, to work around the issue, read any register from the custom chips because *THAT* is sufficient as it synchronizes the CPU to the custom chip bus.


Quote:
Originally Posted by remz View Post
And here's my writing function, optimized to 168 cycles / 54 bytes (depending if no branch were taken and SERDATR was ready of course).
However, how these cycles relate to the custom chip cycles depends on the CPU speed, and thus the time may not be sufficient.
Thomas Richter is offline  
Old Yesterday, 21:07   #22
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,089
Quote:
Originally Posted by hooverphonique View Post
@a/b: perhaps change "addq.b #1, _comm_rx_put+1" to "addq.b #1,(-2,a0)"
That would be too late because a0 is modified twice (+2, +variable) by adda.w (a0)+,a0. And if you do it beforehand, well that's equivalent to the second version I've posted and requires a small change in logic.

Another thing, I'd also do interrupt acknowledge prior to reading SERDAT, which would then act as a chipmem bus flush, so you don't have to worry about double interrupts on newer CPUs. As Thomas pointed out already.
a/b is offline  
Old Today, 01:54   #23
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 56
Posts: 2,097
Quote:
Originally Posted by remz View Post
It is working pretty well now; I would like to share my code here because I love to learn from you about best practices and optimizations.
Here's my receive interrupt function (RBF), I optimized it to the best of my knowledge and got it to 148 cycles / 40 bytes.
Two variables are used:
comm_rx_put is used as a byte which wraps around at 256;
comm_rx_buff is a circular buffer of 256 bytes.

Code:
Irq_RBF:
	move.w 		d1, -(a7)
	move.l 		a0, -(a7)

	move.w		CHIP_BASE+SERDATR, d1

	; acknowledge interrupt only after we have finished processing the received byte
	move.w		#$0800, CHIP_BASE+INTREQ

	lea.l		_comm_rx_buff(pc), a0
	adda.w 		_comm_rx_put(pc), a0
	move.b		d1, (a0)

	addq.b		#1,	_comm_rx_put+1

	move.l 		(a7)+, a0
	move.w 		(a7)+, d1

	rte

SECTION_BSS
	public _comm_rx_put
	public _comm_rx_buff
_comm_rx_put:	dc.w 	0
_comm_rx_buff:  ds.b    256
And here's my writing function, optimized to 168 cycles / 54 bytes (depending if no branch were taken and SERDATR was ready of course).
The function expects D0 to contain the byte value to send.
It uses one variable: comm_tx_checksum, which is used as a cheap sort of checksum.
One particularity is if the caller wants to send a byte value of $D5, this function will emit a second byte of value $5D immediately after.
This is because I use $D5 as a 'end of packet separator' in the game code.

Code:
_Comm_Write_Byte:
	lea $dff018,a0				  ; set SERDATR as base A0
	EOR.B	D0,_comm_tx_checksum
	OR.W	#$0100,D0
.wait_serdatr_ready:
	MOVE.W	 (a0),D1				; SERDATR
	AND.W   #$2000, D1
	BEQ.S	.wait_serdatr_ready
	MOVE.W	D0,$30-$18(a0)			; SERDAT
	
	CMP.W	#$01d5,D0			; if a 0xD5 is sent, then immediately send a 0x5D
	BEQ.S	.send_5d

	RTS

.send_5d
	MOVE.W	#$015d,D0			
.wait_serdatr_ready2:
	MOVE.W	 (a0),D1				; SERDATR
	AND.W   #$2000, D1
	BEQ.S	.wait_serdatr_ready2
	MOVE.W	D0,$30-$18(a0)			; SERDAT
	RTS
I would love to have your input on what could be further or better optimized.
Thank you everyone for your input and participation in this thread (and any threads in fact!)
I never coded for serial, but under Amiga OS some (or maybe all) interrupts are called with set values for A0 and A1 registers.
From my memory a0 is set as $dff000 and a1 as pointer to data or vice versa.
Then programmed interrupt code can be very short.
Perhaps D0/D1/A0/A1 are scratch registers too, then not need to put on stack.
But better check this because, I worked only for audio/timer interrupts.
And it can works different for serial interrupts.
Don_Adan is offline  
Old Today, 03:46   #24
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 56
Posts: 2,097
Code:
_Comm_Write_Byte:
	lea $dff018,a0				  ; set SERDATR as base A0
	EOR.B	D0,_comm_tx_checksum
	OR.W	#$0100,D0
.wait_serdatr_ready:
	MOVE.W	 (a0),D1				; SERDATR
	AND.W   #$2000,D1
	BEQ.S	.wait_serdatr_ready
	MOVE.W	D0,$30-$18(a0)			; SERDAT
	
	CMP.W	#$01d5,D0			; if a 0xD5 is sent, then immediately send a 0x5D
	BEQ.S	.send_5d

	RTS

.send_5d
	MOVE.W	#$015d,D0			
.wait_serdatr_ready2:
	MOVE.W	 (a0),D1				; SERDATR
	AND.W   #$2000, D1
	BEQ.S	.wait_serdatr_ready2
	MOVE.W	D0,$30-$18(a0)			; SERDAT
	RTS
Seems You dont need/use other bits than bit 13.

Then You can try this.

Code:
_Comm_Write_Byte:
	lea $dff018,a0				  ; set SERDATR as base A0
	EOR.B	D0,_comm_tx_checksum
	OR.W	#$0100,D0
.wait_serdatr_ready:
	btst #13-8,(a0)				; SERDATR
	BEQ.S	.wait_serdatr_ready
	MOVE.W	D0,$30-$18(a0)			; SERDAT
	
	CMP.W	#$01d5,D0			; if a 0xD5 is sent, then immediately send a 0x5D
	bne.b	.skipsend_5d
		
.wait_serdatr_ready2:
	btst #13-8,(a0)				; SERDATR
	BEQ.S	.wait_serdatr_ready2
	MOVE.W	#$015d,$30-$18(a0)			; SERDAT
.skipsend_5d
	RTS
Don_Adan is offline  
Old Today, 11:09   #25
hooverphonique
ex. demoscener "Bigmama"
 
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,657
Quote:
Originally Posted by a/b View Post
That would be too late because a0 is modified twice (+2, +variable) by adda.w (a0)+,a0.
Haha, yeah, the +variable part ruins my idea
hooverphonique is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Serial communication? MickGyver Coders. Blitz Basic 4 10 April 2020 16:40
serial communication between Amiga and PC TCH support.Amiga Forever 6 24 March 2020 00:00
CD32 Accelerator reliability .. leonk support.Hardware 4 30 April 2019 19:35
Serial Port <--> Tablet: no communication ral-clan support.WinUAE 0 02 February 2011 19:51
Supercars 2 communication screens jotd Retrogaming General Discussion 11 04 December 2006 18:06

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 23:23.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.09211 seconds with 15 queries