Skip to content

Software PWM VII – A need for speed

October 11, 2014

I try not to waste time on premature optimization but I do like to look under the covers at my code just to see if there’s anything obviously wrong. Here’s the code for the software PWM routines pwmstep and pymcycleN. I would like the total time for these to be on the order of a millisecond so i can use them as time delays.

To summarize the instruction counts below, pwmcycleN is about 90 instructions and pwmstep is about 1400 which is about the 6ms i’m seeing.

In the body of pwmstep, there’s a lot of repeated loading of the globals (PIN4, step, toggle etc) and i’m using the generic OUT(x,y) which must be contributing 300-400 instructions to the total but that’s just going to screw up the duty cycle further.  Converting the whole of pwmstep to assembly will probably solve the speed issue.

pwmcycleN will have 25 inst to start for call return. Then the preamble looks like about 25. the outer loop is about 10, and the inner loop is 10*8 plus the pwmstep instructions. So say for a call of pwmcycleN(20), the fixed overhead is 2.5/cycle, the outer loop adds 10, and the inner loop 80 – call it 90.

_pwmcycleN:		;framesize=10
	pushf R6	;opt11
	pushl R7	;opt11
	reserve 4; save room for outgoing arguments
	cpy2 R7,R12; function(2054) 1
;void pwmcycleN(unsigned int howmany){ //run howmany*8 steps of the software pwm
	lbr L11
L10:
;	while(howmany-->0){
;		for(i=8;i>0;i--){
	ldaD R6,8; reg:acon
	lbr L16
L13:
;			pwmstep();
	Ccall _pwmstep
;		}
L14:
;		for(i=8;i>0;i--){
	decm R6,1
L16:
	jnzU2 R6,L13; NE 0
;	}
L11:
;	while(howmany-->0){
	cpy2 R11,R7 ;LOADU2(reg) ;opt1.1
	decm R7,1
	jnzU2 R11,L10; NE 0
;}
L9:
	release 4; release room for outgoing arguments
	popr R7
	popr R6
	Cretn

so pwmstep starts with 25 for call return and the preamble is only 4.
The body is about 130 for steps 0-7 plus 140 for the table reset.

8 cycles then takes about 1200+140 instructions

_pwmstep:		;framesize=6
	reserve 4
;void pwmstep(){	//run one step of the software pwm cycle
;	PIN4^=toggle[step]; out(4,PIN4); //toggles the bit off if the duty cycle is over
4	ldaD R11,_PIN4; reg:acon
5	ld1 R10,'D',(_PIN4),0
2	zExt R10 ;CVUI2: widen unsigned char to signed int (zero extend)
8	ld2 R9,'D',(_step),0 ;reg:INDIRU2(addr)
7	ld1 R9,'O',R9,(_toggle)
2	zExt R9 ;CVUI2: widen unsigned char to signed int (zero extend)
12	alu2 R10,R10,R9,xor,xor
2	str1 R10,R11; ASGNU1(indaddr,reg)		DH
4	ldaD R12,4; reg:acon
5	ld1 R13,'D',(_PIN4),0
2	zExt R13 ;CVUI2: widen unsigned char to signed int (zero extend)
25+16	Ccall _out; CALLI2(ar)
;	toggle[step++]=0;
8	ld2 R11,'D',(_step),0 ;reg:INDIRU2(addr)
4	cpy2 R10,R11
1	incm R10,1
8	st2 R10,'D',(_step),0; ASGNU2(addr,reg)
6	ldA2 R11,'O',R11,(_toggle); reg:addr
2	str1I 0,R11; ASGNU1(indaddr,acon)	DH
;	if (8==step){//if we're done a full pass
8	ld2 R11,'D',(_step),0 ;reg:INDIRU2(addr)
4	jneU2I R11,8,L6; NE

;		step=0;	//reset the index
3	ld2z R11
8	st2 R11,'D',(_step),0; ASGNU2(addr,reg)
;		toggle[dct[0]]|=1; //set the end of the duty cycle for bit 0
6	ld1 R11,'D',(_dct),0
2	zExt R11 ;CVUI2: widen unsigned char to signed int (zero extend)
6	ldA2 R11,'O',R11,(_toggle); reg:addr
2	ldn1 R10,R11	;opt14*
2	zExt R10 ;CVUI2: widen unsigned char to signed int (zero extend)
12	alu2I R10,R10,1,ori,ori ;removed copy
2	str1 R10,R11; ASGNU1(indaddr,reg)		DH
;		toggle[dct[1]]|=2; //set the end of the duty cycle for bit 1
6	ld1 R11,'D',(_dct+1),0
2	zExt R11 ;CVUI2: widen unsigned char to signed int (zero extend)
6	ldA2 R11,'O',R11,(_toggle); reg:addr
2	ldn1 R10,R11	;opt14*
2	zExt R10 ;CVUI2: widen unsigned char to signed int (zero extend)
12	alu2I R10,R10,2,ori,ori ;removed copy
2	str1 R10,R11; ASGNU1(indaddr,reg)		DH
;		toggle[0]^=~PIN4; //set up with current state of port4 low bits
4	ldaD R11,_toggle; reg:acon
6	ld1 R10,'D',(_toggle),0
2	zExt R10 ;CVUI2: widen unsigned char to signed int (zero extend)
6	ld1 R9,'D',(_PIN4),0
2	zExt R9 ;CVUI2: widen unsigned char to signed int (zero extend)
12	alu2I R9,R9,-1,xri,xri; was?	cpy2 R9,R9+xor2I R9,-1
12	alu2 R10,R10,R9,xor,xor
2	str1 R10,R11; ASGNU1(indaddr,reg)		DH
;		toggle[0]&=0x03; //only the pwm bits are set
4	ldaD R11,_toggle; reg:acon
6	ld1 R10,'D',(_toggle),0
2	zExt R10 ;CVUI2: widen unsigned char to signed int (zero extend)
12	alu2I R10,R10,3,ani,ani
	;removed ?	cpy2 R10,R10
2	str1 R10,R11; ASGNU1(indaddr,reg)		DH
;	}
L6:
;}
L5:
4	release 4
	Cretn

2

Advertisements

From → Uncategorized

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: