I use similar code for numbers greater then 1.
Something like this:
Code:A VAR WORD B,C,D,Add VAR BYTE INC: A=A+Add IF A>255 THEN A=A-255 B=B+1 IF B=0 THEN C=C+1 IF C=0 THEN D=D+1 ENDIF ENDIF ENDIF
I use similar code for numbers greater then 1.
Something like this:
Code:A VAR WORD B,C,D,Add VAR BYTE INC: A=A+Add IF A>255 THEN A=A-255 B=B+1 IF B=0 THEN C=C+1 IF C=0 THEN D=D+1 ENDIF ENDIF ENDIF
Last edited by pedja089; - 26th August 2011 at 14:10.
Hi,
Here's a piece of code working with a 32bit accumulator, the lookuptable from the code Hank linked to and the resulting waveform plotted in Excel with addvalues of:
1) 512500
2) 128500
3) 22825
The add routine works with two words instead of four bytes and takes ~86 cycles normally but 121 cycles when it overflows. Not the most effecient code for sure but it does seem to work. If you're running at 32Mhz and interrupting at 20kHz that's still 400 cycles between interrupts.Code:LSW VAR WORD ' Least significat word of accumulator MSW VAR WORD ' Most significatn word of accumulator ADDL VAR WORD ' Least significant work of value to add ADDH VAR WORD ' Most significant word of value to add Out VAR BYTE ' This is the actual output from the lookup table Temp VAR WORD OverFlow VAR BIT ' Gets set when 32bit accumulator overflows. i VAR WORD Init: LSW = 0 MSW = 0 AddL = 500 AddH = 2000 ' 50*256+500=768500 Pause 3000 Main: For i = 1 to 1000 OverFlow = 0 TMR1H = 0 TMR1L = 0 Gosub Add Gosub GetValue HSEROUT["Count: ", DEC4 i, " MSW: ", DEC5 MSW, " LSW: ", DEC5 LSW, " Overflow: ", BIN Overflow, " Out: ", DEC Out, " Ticks: ", DEC5 TMR1H*256+TMR1L, 13] Pause 5 NEXT END Add: T1CON = 1 ' This is just used to measure the execution time Temp = LSW ' Remember least significant word LSW = LSW + ADDL ' Add low word If LSW < Temp Then ' Did we wrap around/overflow? MSW = MSW + 1 ' Increment high word If MSW = 0 Then OverFlow = 1 ' Did we overflow high word? ENDIF Temp = MSW ' Remember high word MSW = MSW + ADDH ' Add high word If MSW < Temp Then ' Did we wrap around/overflow? OverFlow = 1 ' Set flag ENDIF T1CON = 0 RETURN GetValue: Lookup MSW.HighBYTE, [$80,$83,$86,$89,$8C,$8F,$92,$95,$98,$9C,$9F,$A2,$A5,$A8,$AB,$AE,$B0,$B3,$B6,$B9,$BC,$BF,$C1,$C4,_ $C7,$C9,$CC,$CE,$D1,$D3,$D5,$D8,$DA,$DC,$DE,$E0,$E2,$E4,$E6,$E8,$EA,$EC,$ED,$EF,$F0,$F2,$F3,$F5,$F6,$F7,$F8,$F9,$FA,$FB,$FC,$FC, _ $FD,$FE,$FE,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FE,$FE,$FD,$FC,$FC,$FB,$FA,$F9,$F8,$F7,$F6,$F5,$F3,$F2,$F0,$EF,$ED,$EC, _ $EA,$E8,$E6,$E4,$E2,$E0,$DE,$DC,$DA,$D8,$D5,$D3,$D1,$CE,$CC,$C9,$C7,$C4,$C1,$BF,$BC,$B9,$B6,$B3,$B0,$AE,$AB,$A8,$A5,$A2,$9F,$9C, _ $98,$95,$92,$8F,$8C,$89,$86,$83,$7F,$7C,$79,$76,$73,$70,$6D,$6A,$67,$63,$60,$5D,$5A,$57,$54,$51,$4F,$4C,$49,$46,$43,$40,$3E,$3B, _ $38,$36,$33,$31,$2E,$2C,$2A,$27,$25,$23,$21,$1F,$1D,$1B,$19,$17,$15,$13,$12,$10,$0F,$0D,$0C,$0A,$09,$08,$07,$06,$05,$04,$03,$03, _ $02,$01,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$01,$02,$03,$03,$04,$05,$06,$07,$08,$09,$0A,$0C,$0D,$0F,$10,$12,$13, _ $15,$17,$19,$1B,$1D,$1F,$21,$23,$25,$27,$2A,$2C,$2E,$31,$33,$36,$38,$3B,$3E,$40,$43,$46,$49,$4C,$4F,$51,$54,$57,$5A,$5D,$60,$63, _ $67,$6A,$6D,$70,$73,$76,$79,$7C],Out RETURN
/Henrik.
Wow Henrik...what can I say (thank heavens for folks like you & others on here)
I won't pretend to understand it all (once numbers start going above 256 values "woah, there goes scary stuff!").
re this bit...
Not understanding the bolded bits - can you please let me know what you're doing there?Code:Init: LSW = 0 MSW = 0 AddL = 500 AddH = 2000 ' 50*256+500=768500
I'm trying to see how/where I would enter what in DDS terms is called the tuning word (essentially the number that gets added to the accumulator each interrupt?
Also, I was hoping (eventually) that the tuning word would arrive serially (either being calculated manually or sent from another pic)....the maths are going to be a bit troubling...to glean the tuning word to set the required output frequency, it's
required frequency/interrupt rate * accumulator size
so for a wanted frequency of 4971Hz involving a 32 bit accumulator & and say an interupt rate of 20,000Hz
(4971/20000) * 4294967296
...that's gonna be a challenge in an 8 bit PIC?
Last edited by HankMcSpank; - 27th August 2011 at 00:45.
Hi,
You have the 32bit accumulator built up by the two WORDS, LSW and MSW. Then you have the 32bit value which gets added to the accumulator each iteration (each interrupt in your case) and that's the ADDL and ADDH words. Perhaps it's the invalid comment that's causing confusion....?
Lets take a 16bit WORD as an example.
myValue VAR WORD
myValue = 12345
Now, the WORD, which is two bytes holds the value 12345, if you'd look at the high byte of that word its value would be 48 and the value in the low byte would be 57. Why? Because 48*256+57=12345
Same thing with our accumulator and "adder value" but this time we're working with two WORDS.
ADDL = 500
ADDH = 2000
2000 * 65536 + 500 = 512500 which is the value getting added to the accumulator each time. In your example, 4971/20000*2^32 the, value to add the accumulator each time is 1067514121 or ADDH=16288, ADDL=64753. Or, which might be easier expressed in hex: 3FA0F909, see there's your two words, ADDH=$3FA0, ADDL=$F909
Let me know if you try it on some real hardware.
/Henrik.
Thanks Henrik....excellent stuff.
So, using your code where I have say a 20khz interrupt rate in place, would it be the extract below that goes into the actual 'accumulator addition & lookup' interrupt subroutine?
Code:Add: ' start of interrupt interrupt routine? Temp = LSW ' Remember least significant word LSW = LSW + ADDL ' Add low word If LSW < Temp Then ' Did we wrap around/overflow? MSW = MSW + 1 ' Increment high word If MSW = 0 Then OverFlow = 1 ' Did we overflow high word? ENDIF Temp = MSW ' Remember high word MSW = MSW + ADDH ' Add high word If MSW < Temp Then ' Did we wrap around/overflow? OverFlow = 1 ' Set flag ENDIF ' ' Lookup MSW.HighBYTE, [$80,$83,$86,$89,$8C,$8F,$92,$95,$98,$9C,$9F,$A2,$A5,$A8,$AB,$AE,$B0,$B3,$B6,$B9,$BC,$BF,$C1,$C4,_ $C7,$C9,$CC,$CE,$D1,$D3,$D5,$D8,$DA,$DC,$DE,$E0,$E2,$E4,$E6,$E8,$EA,$EC,$ED,$EF,$F0,$F2,$F3,$F5,$F6,$F7,$F8,$F9,$FA,$FB,$FC,$FC, _ $FD,$FE,$FE,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FE,$FE,$FD,$FC,$FC,$FB,$FA,$F9,$F8,$F7,$F6,$F5,$F3,$F2,$F0,$EF,$ED,$EC, _ $EA,$E8,$E6,$E4,$E2,$E0,$DE,$DC,$DA,$D8,$D5,$D3,$D1,$CE,$CC,$C9,$C7,$C4,$C1,$BF,$BC,$B9,$B6,$B3,$B0,$AE,$AB,$A8,$A5,$A2,$9F,$9C, _ $98,$95,$92,$8F,$8C,$89,$86,$83,$7F,$7C,$79,$76,$73,$70,$6D,$6A,$67,$63,$60,$5D,$5A,$57,$54,$51,$4F,$4C,$49,$46,$43,$40,$3E,$3B, _ $38,$36,$33,$31,$2E,$2C,$2A,$27,$25,$23,$21,$1F,$1D,$1B,$19,$17,$15,$13,$12,$10,$0F,$0D,$0C,$0A,$09,$08,$07,$06,$05,$04,$03,$03, _ $02,$01,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$01,$02,$03,$03,$04,$05,$06,$07,$08,$09,$0A,$0C,$0D,$0F,$10,$12,$13, _ $15,$17,$19,$1B,$1D,$1F,$21,$23,$25,$27,$2A,$2C,$2E,$31,$33,$36,$38,$3B,$3E,$40,$43,$46,$49,$4C,$4F,$51,$54,$57,$5A,$5D,$60,$63, _ $67,$6A,$6D,$70,$73,$76,$79,$7C],Out @ INT_RETURN
Last edited by HankMcSpank; - 27th August 2011 at 11:32.
Henrik, rather than have two threads running, if you don't mind I'll cut/paste your input over to the other thread http://www.picbasic.co.uk/forum/show...921#post106921 , which perhaps has a more appropriate title for the content we are now discussing (allowing others to find it easier)
Bookmarks