First attempt at assembly
AJM
Posts: 171
I’m trying to introduce myself to pasm. While I haven’t mastered spin as of yet, I feel I really need to understand at least some assembly to understand most of the code floating around this place.
I need to supply an analog voltage (0 ~ 3.3V will be fine) for a project I’m attempting. Since there is an example of this in the application notes, I thought I would start there.
Below is the file I am referencing:
Assuming that we have a 5Mhz crystal and pll = 16. Let me know if I understand this correctly.
The first cog, using loops, sets the variable ‘parameter’ to 2000 different values. Values are between 0 ~ 2^32 roughly. This occurs every 12.5us.
Meanwhile the second cog, which was started by the cognew(@entry, @parameter) command, has set up the counters, moved the value in cnt to time, added time to period and stored that value into time.
Next, I assume that the loop is started automatically in a linear fashion. The address of parameter is passed through par and its current value is stored, in this case, into the variable value.
The loop waits for 25us and then updates frqa. Jmp #:loop just repeats the loop. This effectively gives an analog output from 0 ~ 3.3V in a sawtooth wave.
If this is correct I have a few questions. I must be missing something however. I don’t understand how the cog that is updating the counters is accurate. Isn’t it missing every other value of parameter because it’s waiting twice as long?
More questions to come later. Thanks for the help.
I need to supply an analog voltage (0 ~ 3.3V will be fine) for a project I’m attempting. Since there is an example of this in the application notes, I thought I would start there.
Below is the file I am referencing:
{{ Demonstration of scaling Duty Cycle 10kΩ APIN ─┳── Out │ .1µF  Delta modulation has no fundamental freq but has quantization noise }} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 VAR long parameter PUB go | x cognew(@entry, @parameter) repeat repeat x from 0 to period parameter := $20C49B * x '$1_0000_0000 / period waitcnt(1000 +cnt) DAT org entry mov dira, diraval mov ctra, ctraval mov time, cnt add time, period :loop rdlong value, par waitcnt time, period mov frqa, value jmp #:loop diraval long |< 1 + |< 0 ctraval long %00111 << 26 + 1<<9 + 0 'NCO/PWM APIN=0 BPIN=1 period long 2000 '800kHz period (_clkfreq / period) time res 1 value res 1
Assuming that we have a 5Mhz crystal and pll = 16. Let me know if I understand this correctly.
The first cog, using loops, sets the variable ‘parameter’ to 2000 different values. Values are between 0 ~ 2^32 roughly. This occurs every 12.5us.
Meanwhile the second cog, which was started by the cognew(@entry, @parameter) command, has set up the counters, moved the value in cnt to time, added time to period and stored that value into time.
Next, I assume that the loop is started automatically in a linear fashion. The address of parameter is passed through par and its current value is stored, in this case, into the variable value.
The loop waits for 25us and then updates frqa. Jmp #:loop just repeats the loop. This effectively gives an analog output from 0 ~ 3.3V in a sawtooth wave.
If this is correct I have a few questions. I must be missing something however. I don’t understand how the cog that is updating the counters is accurate. Isn’t it missing every other value of parameter because it’s waiting twice as long?
More questions to come later. Thanks for the help.
Comments
So, yes,·you are·correct.· The SPIN code is updating parameter every 1000 clock cycles, while the PASM code is reading parameter every 2000 clock cycles.· I suspect the problem is "period" is being used for two different purposes.· There should be a "delay" variable which is used for both waitcnt delays.
There's also a gotcha in the code even with that change.· Note that the SPIN code uses waitcnt( cnt + delay) while the PASM code uses waitcnt( time ); time += delay.· The SPIN code is waiting delay cycles from the start of waitcnt, while the PASM code is waiting delay cycles from the previous waitcnt.· So the SPIN loop will take longer than the PASM code.· I'd recommend changing the SPIN code to be more like the PASM code: initialize time := cnt outside of the repeats (you can reuse the variable since the PASM variable will be in COG RAM) then use waitcnt( time += delay ) inside the repeats.
In fact, there's no real reason to have a waitcnt in the PASM code at all.· It can simply read parameter and update frqa in a tight loop.· All of the delay is done by the SPIN code.· (You could also argue there's no reason to have two separate routines, the functionality of the PASM code could be done in SPIN just as easily.· It also could be done in pure PASM, but then you'd need to code the multiply routine.)
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Composite NTSC sprite driver: Forum
NTSC & PAL driver templates: ObEx Forum
OnePinTVText driver: ObEx Forum
I have another concern about the below code:
I really do not understand the rdlong instruction. Couldn't this be replaced with a mov? Or why couldn't the third line be changed to "mov frqa, par." I'm sure its necessary but I do not know why.
Also, is there necessarily a reason to have the counter in differential mode? Couldn't this be done in single ended mode?
Thanks again,
By the way, wouldn't you want to swap the position of the MOV and the WAITCNT? That way the FRQA value is updated immediately, before the wait.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
April, 2008: when I discovered the answers to all my micro-computational-botherations!
Some of my objects:
MCP3X08/4 ADC Driver - Programmable Schmitt inputs, frequency reading, and more!
Simple Propeller-based Database - Making life easier and more readable for all your EEPROM storage needs.
String Manipulation Library - Don't make strings the bane of the Propeller, bend them to your will!
Post Edited (Bobb Fwed) : 10/2/2009 4:19:06 PM GMT
I see your point about swapping the MOV and WAITCNT. However, as Eric mentioned, the waitcnt is probably irrelevant. This isn't my code though. I found this in the propeller application notes, AN001, found here.
I want to be able to use the prop as an DAC in the end. I thought this would be a good time to at least familiarize myself with at least some pasm.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
April, 2008: when I discovered the answers to all my micro-computational-botherations!
Some of my objects:
MCP3X08/4 ADC Driver - Programmable Schmitt inputs, frequency reading, and more!
Simple Propeller-based Database - Making life easier and more readable for all your EEPROM storage needs.
String Manipulation Library - Don't make strings the bane of the Propeller, bend them to your will!