Ok...
Code:INCLUDE "DT_INTS-14.bas" ; Base Interrupt System INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts '@ DEVICE pic16F777, HS_OSC ; System Clock Options '@ DEVICE pic16F777, WDT_OFF ; Watchdog Timer '@ DEVICE pic16F777, PWRT_ON ; Power-On Timer '@ DEVICE pic16F777, MCLR_OFF ; Brown-Out Detect '@ DEVICE pic16F777, PROTECT_OFF @ __CONFIG _CONFIG1, _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC define OSC 20 DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1 DEFINE HSER_SPBRG 10 ' 115200 Baud @ 20MHz, -1,36% DEFINE HSER_CLROERR 1 ' Clear overflow automatically clear MODO VAR BYTE[3] DIST VAR BYTE SAG VAR BYTE[3] SAG[0] = 0 SAG[1] = 0 SAG[2] = 0 SWELL VAR BYTE SWELL = 0 CTRL VAR BYTE LOAD VAR WORD RA VAR BYTE RB VAR BYTE RC VAR BYTE RD VAR BYTE RA = 0 RB = 1 RC = 0 RD = 0 V VAR BYTE VA VAR BYTE VB VAR BYTE VC VAR BYTE CONTA VAR BYTE CONTB VAR BYTE CONTC VAR BYTE CONT VAR BYTE INDEX VAR BYTE FLAG VAR BYTE X VAR BYTE FLAG = 0 CONTA = 0 CONTB = 23 CONTC = 47 modo[0] = 1 modo[1] = 1 modo[2] = 1 ' Set CCPx pins to outputs TRISC.2 = 0 ' CCP1 output TRISC.1 = 0 ' CCP2 output (could also be assigned to RB3) TRISB.5 = 0 ' CCP3 output TRISC.7 = 1 TRISC.6 = 0 TRISD.0 = 0 ' Set CCP modules to PWM mode CCP1CON = %00001100 ' Mode select = PWM CCP2CON = %00001100 ' Mode select = PWM CCP3CON = %00001100 ' Mode select = PWM INTCON = %11000000 LOAD = 65250' 4320Hz 'LOAD = 0 TMR1H = LOAD.HIGHBYTE TMR1L = LOAD.LOWBYTE T1CON = %00000001 PIE1.0 = 1 PR2 = 200 'PR2 = 62 PORTD.0 = 0 ' Set TMR2 up for 1:1 prescale & turn it on T2CON = %00000100 ' TMR2 ON 1:1 prescale 'T2CON = %00011100 ' TMR2 ON 1:1 prescale ASM INT_LIST macro ;IntSource, Label, Type, ResetFlag? INT_Handler TMR1_INT, _Timer1, PBP, yes INT_Handler RX_INT, _GetChar, PBP, yes INT_Handler TX_INT, _SendChar, PBP, yes endm INT_CREATE ; Creates the interrupt processor ENDASM @ INT_ENABLE TMR1_INT ; Habilita interrupção do TMR1 @ INT_ENABLE RX_INT ;- enable the interrupt @ INT_ENABLE TX_INT ;- enable the interrupt MAIN: IF FLAG = 1 THEN PORTD.0 = 1 flag = 0 CONTA = CONTA + 1 CONTB = CONTB + 1 CONTC = CONTC + 1 if contA = 71 then contA = 0 if contB = 71 then contB = 0 if contC = 71 then contC = 0 index = conta if RA.0 = 1 then DIST = RB SAG[0] = RC MODO[0] = DIST ELSE DIST = MODO[0] ENDIF GOSUB tabela va = (v*(100-sag[0]))/100 index = contB if RA.1 = 1 then DIST = RB SAG[1] = RC MODO[1] = DIST ELSE DIST = MODO[1] ENDIF GOSUB tabela vb = (v*(100-SAG[1]))/100 index = contC if RA.2 = 1 then DIST = RB SAG[2] = RC MODO[2] = DIST ELSE DIST = MODO[2] ENDIF GOSUB tabela vc = (v*(100-SAG[2]))/100 RA = 0 GOSUB SAIDA PORTD.0 = 0 endif GOTO MAIN TABELA: SELECT CASE DIST CASE 1: ' Fundamental LOOKUP INDEX, [100,109,118,126,135,143,151,158,165,171,177,183,187,191,195,197,199,200,200,199,198,196,193,189,185,180,175,168,162,154,147,139,130,122,113,104,96,87,78,70,61,53,46,38,32,25,20,15,11,7,4,2,1,0,0,1,3,5,9,13,17,23,29,35,42,49,57,65,74,82,91], V CASE 2: ' 3 com 20% LOOKUP INDEX, [100,114,127,140,152,162,170,177,182,185,187,187,187,185,184,182,181,180,180,180,181,182,184,185,187,187,187,185,182,177,170,162,152,140,127,114,100,86,73,60,48,38,30,23,18,15,13,13,13,15,16,18,19,20,20,20,19,18,16,15,13,13,13,15,18,23,30,38,48,60,73,86], v CASE 3: ' 3 com 20% + 5 com 10% LOOKUP INDEX, [100,118,135,150,161,170,175,178,178,178,177,177,178,180,182,185,188,189,190,189,188,185,182,180,178,177,177,178,178,178,175,170,161,150,135,118,100,82,65,50,39,30,25,22,22,22,23,23,22,20,18,15,12,11,10,11,12,15,18,20,22,23,23,22,22,22,25,30,39,50,65,82], V CASE 4: ' 3 com 20% + 5 com 10% + 7 com 10% LOOKUP INDEX, [100,124,144,159,168,171,170,168,168,171,175,181,187,190,190,188,184,181,180,181,184,188,190,190,187,181,175,171,168,168,170,171,168,159,144,124,100,76,56,41,32,29,30,32,32,29,25,19,13,10,10,12,16,19,20,19,16,12,10,10,13,19,25,29,32,32,30,29,32,41,56,76], V CASE 5: ' 5 com 10% + 7 com 20% lookup index, [100,122,139,149,151,147,141,136,137,145,157,172,186,194,197,194,188,183,181,183,188,194,197,194,186,172,157,145,137,136,141,147,151,149,139,122,100,78,61,51,49,53,60,64,63,55,43,28,14,6,3,6,12,17,19,17,12,6,3,6,14,28,43,55,63,64,59,53,49,51,61,78], v CASE 6: return CASE 7: return end select return SAIDA: CCP1CON.4 = VA.0 CCP1CON.5 = VA.1 CCPR1L = VA >> 2 CCP2CON.4 = VB.0 CCP2CON.5 = VB.1 CCPR2L = VB >> 2 CCP3CON.4 = VC.0 CCP3CON.5 = VC.1 CCPR3L = VC >> 2 RETURN Timer1: TMR1H = load.highbyte TMR1L = load.lowbyte FLAG = 1 @ INT_RETURN GetChar: HSERIN [dec RA] HSERIN [dec RB] HSERIN [dec RC] HSERIN [dec RD] @ INT_ENABLE TX_INT ;- enable the interrupt @ INT_RETURN SendChar: 'hserout [dec cod[0], "-", dec cod[1], "-", dec cod[2], "-", dec cod[3]] @ INT_DISABLE TX_INT ;- disable the interrupt @ INT_RETURN END
Sylvio,
Ah ha, there's the missing info.
With the lines ...I'm measuring each one at about 125us. There's 3 of them, so that's 375us, plus the 70us I measured for the main loop last time, for a total of around 450us.Code:va = (v*(100-sag[0]))/100
Timer1 is overflowing every ~230us, so it's definately missing the Flag's.
<br>
DT
"Ah ha..."
Funny.. I'm trying to imagine the Eureka's face you had done...
Well, I kind of did not get it. You are saying that the program is wasting time at this statement?
Why would it be happening? 125us just to make 1 subtract, 1 mult and 1 div?Code:va = (v*(100-sag[0]))/100
Thanks Darrel!
Last edited by sirvo; - 9th August 2008 at 01:40.
Sylvio,
Yup, multiplication and division takes a LOT of loops to do.
In this thread I had measured a single 16/16 divide at over 76us (382 instructions).
Keep in mind that in PBP, ALL mutiplications and divisions are done as a 16-bit operation. So even though the variables are BYTE's, it takes the same time as if they were WORD's.
I haven't timed a 16*16 multiply yet, but from these results I'd say it's probably just under 50us.
Time to find a new way to do the math.
<br>
DT
And if I remember right, ALL mult's and div's done with PBPL in 2.50B are done as signed-31-bit operations. So, now it's even 'worse'!
Sounds like it might be time for a small assembly routine for 8 and 16 bit math when speed counts...something like: @ mult16, @ mult8, @ div16, @ div8
I've been meaning to do it...sometime...when I get time...to save time...
That would be really handy. And if you do, here's a good place to start ...
PIC Microcontoller Basic Math Methods
http://www.piclist.com/techref/microchip/math/basic.htm
<br>
DT
OR, increase timer1 interrupt and decrease the number of the sine table points..
However, I think that 71 points is on the edge for generating a good signal in this aplication. Reducing this number would not let the application to create good harmonics distortion due to the big step between these number...Well, all of this would be answered trying, right?
I'll get an osc. next thursday... until there I've got to wait...
Thanks again!
Sylvio,
sirvo> OR, increase timer1 interrupt and decrease the number of the sine table points..
Actually, I was thinking you should have a larger table at a faster rate.
But it'll take a few changes.
Here's a couple things that will help speed things up.
First, change the interrupt TYPE for TMR1_INT to ASM.
The handler only set's the flag and loads the timer, so it doesn't need to save all the PBP system registers. This should save about 40us.<hr>
Then if the SAG() values ranged from 0-255 instead of 0-100, this could replace what you had ...It will save 75us each time, which brings the whole loop down to 220us. Just barely under the Timer1_INT period. But if you want to add more features, or increase the sin table, there won't be any time left.Code:va = v */ (255-sag[0]+1)
<hr>
Going a bit further, here's a little asm routine that'll really help.
It Scales an 8-bit value to another 8-bit value.
Essentially it does Result=Value*(Scale+1), with the actual result being in the HighByte of the R2 variable.
With this you can do ...Here's the ASM part. Put it somewhere above the Main loop.Code:; va = (v*(100-sag[0]))/100 R0 = V ; Put the value in R0 R1 = 255-SAG[0] ; Inverted SAG to R1 CALL Scale8 ; Scale R0*(R1+1) VA = R2.HighByte ; result is in R2.HighByteUsing the above code, each call to Scale8 takes about 18us or 54us for all three. With 70us for the rest, it ends up doing the whole thing in about 125us. Well within the 230us periods. And time left over for a bigger/faster table.Code:ASM ; ---- [Scale8 - Scale an 8-bit value]---------- ; Input: R0 = Value to scale | ; R1 = Scale (0-255) | ; Output: R2 = R0*(R1+1) | ; Result is in R2.HighByte | ;--------------------------------------------------- goto OverScale8 _Scale8 clrf R2 ; result LowWord clrf R2 + 1 ; result HighWord movlw 8 movwf R3 ; Loop counter movf R1, W ; Load Scale in W reg bcf STATUS, C ; clear carry Scale8Loop rrf R0, F ; Rotate the Value, lsb goes to carry btfsc STATUS, C ; if the carry = 1 then addwf R2 + 1, F ; add Scale to result.highbyte rrf R2 + 1, F ; rotate the result.highbyte, lsb goes to carry rrf R2, F ; rotate carry into result.lowbyte decfsz R3, F ; next loop goto Scale8Loop addwf R2, F ; add 1 more Scale btfsc STATUS, C ; if carry incf R2 + 1, F ; inc highbyte return ;----[Macro to make things easier]------------------ Scale8 macro Value, Scale, Bout MOVE?BB Value, R0 MOVE?BB Scale, R1 L?CALL _Scale8 MOVE?BB R2 + 1, Bout endm OverScale8 ENDASM ; ---- [End of Scale8]-----------------------
I'm not using the macro at this point. It's just there for future reference.
Just remember ... SAG is 0-255 now. So if you need to convert it...Which is much like what you had in the beginning. But now it's only done when setting the SAG values, instead of 12000 times a second.Code:SAG(0) = SAG0value*255/100
HTH,
DT
Bookmarks