Basic Question about cog memory
Mad A
Posts: 17
So I have successfully generated a sin wave, output on 8 pins and sent to a DAC. I am trying to cycle through the wave once and store the values to COG memory so I can then spit them out faster because I won't be reading from hub memory every time. I cannot get this to work and would appreciate any direction/corrections.
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 VAR long index word angles[360] PUB Get_samples repeat index from 0 to 360 angles[index] := index*8192/360 cognew(@begin,@angles[0]) DAT begin mov address, par mov dira,#$FF :loop rdword sin, address add address, #2 call #getsin mov time,cnt add time,delay waitcnt time,delay sar sin, #9 add sin, #$80 mov cogmem, sin 'write sin cog memory rather than output pins 'mov outa,cogmem add cogmem, #2 'increment memory location djnz ctr,#:loop'decrement counter and restart loop 'mov ctr,#360 'Initialize counter. 'mov address,par 'jmp #:loop mov :rdmem,start mov ctr,#360 :rdmem mov cogmem,0-0 mov outa,cogmem add cogmem, #2 djnz ctr,#:rdmem mov :rdmem,start mov ctr,#360 jmp #:rdmem getsin test sin,sin_90 wc 'get quadrant 2|4 into c test sin,sin_180 wz 'get quadrant 3|4 into nz negc sin,sin 'if quadrant 2|4, negate offset or sin,sin_table 'or in sin table address >> 1 shl sin,#1 'shift left to get final word address rdword sin,sin 'read word sample from $E000 to $F000 negnz sin,sin 'if quadrant 3|4, negate sample getsin_ret ret ' (this subroutine adapted from Prop manual) sin_90 long $0800 sin_180 long $1000 sin_table long $E000 >>1 sin long 0 ptr long 0 ctr long 360 cntstart long 360 address long 0 cogmem long $03C0 start long $03C0 delay long 9 time res 1
Comments
Once read to COG Ram, no need for HUB calls.
It looks like you are only using 29 of the 492 memory locations available in cog ram, so the 360 values should fit.
Also note that COG memory is always addressed in longs, not bytes.
So the code above should look roughly like (note that I give no guarantees, just giving a flavor!):
There's a similar problem in the loop:
I gather your intention there is to copy the 360 sin values starting at "start" into outa. For that you would have to do something like: You can optimize this a bit by actually incrementing the instruction at :rdmem directly, since the source is in the low bits of the instruction, but that's an advanced topic :-).
Finally note that you will need to reserve 360 long words, not 720 bytes, for the array, since in COG memory the smallest addressable unit is a long word (4 bytes). You could get fancy and do two samples at once by shifting and masking, but that's a bit more work.
Eric
I tried your code for the first loop and I no longer get a sinusoid on the scope when I uncomment mov outa,cogmem and the instructions at the end to keep the loop going. Rather I get a sawtooth wave much like the lower loop gives me. Any ideas?
Andy
Eric
I did try doing outa, sin and it worked but my goal is to get the sin data into the memory location cogmem so I can access it later (in the second loop). Essentially I want to read a full period into memory and then just spit out samples. So how do I get the DATA into "cogmem" rather than having it just be a pointer? Sorry if I'm being dense, I appreciate the help. I am also about to look at the other post from kuroneko about a different approach.
You can not store 360 values into a single cogmem location. You need to reserve 360 longs for cogmem, eighter with res as kuroneko has shown or with: Then these two loops can store and replay the sine values into/from this data-table: Andy
Before I forget, your SPIN loop should stop at 359!