MCP3208.spin
mynet43
Posts: 644
I'm using the MCP3208.spin routine provided with the Propeller Tool.
There's one line of code that I don't understand. Here's a snippet of my code:
CON
dpin = 13
cpin = 14
spin = 15
mode = $FF
OBJ
adc : "MCP3208"
PUB start | chan
adc.start(dpin, cpin, spin, mode)
repeat chan from 0 to 7
adc.in(chan)
adc.average(chan, 10)
etc, etc
Here's my question: the MCP3208 object has a global variable called 'count'.
When you call adc.start, it calls the routine adc.startx, which initializes count to zero.
When you call the entry adc.average it consists of the following code:
PUB average(channel, n) : sample | c
c := count
repeat n
repeat while c == count
sample += ins.word[noparse][[/noparse]channel]
c++
sample /= n
I understand everything except the line: repeat while c == count, which has nothing indented below it.
It looks as if count is initialized to zero, c is set equal to count and
the "repeat while c == count" should be the same as "repeat while TRUE",
which would loop forever. I know there is a c++ below but it shouldn't get
to this one if it's stuck in the loop.
I know I'm probably missing something because the code apparently works.
Help me understand why that line is there.
Thanks for your help.
Jim
There's one line of code that I don't understand. Here's a snippet of my code:
CON
dpin = 13
cpin = 14
spin = 15
mode = $FF
OBJ
adc : "MCP3208"
PUB start | chan
adc.start(dpin, cpin, spin, mode)
repeat chan from 0 to 7
adc.in(chan)
adc.average(chan, 10)
etc, etc
Here's my question: the MCP3208 object has a global variable called 'count'.
When you call adc.start, it calls the routine adc.startx, which initializes count to zero.
When you call the entry adc.average it consists of the following code:
PUB average(channel, n) : sample | c
c := count
repeat n
repeat while c == count
sample += ins.word[noparse][[/noparse]channel]
c++
sample /= n
I understand everything except the line: repeat while c == count, which has nothing indented below it.
It looks as if count is initialized to zero, c is set equal to count and
the "repeat while c == count" should be the same as "repeat while TRUE",
which would loop forever. I know there is a c++ below but it shouldn't get
to this one if it's stuck in the loop.
I know I'm probably missing something because the code apparently works.
Help me understand why that line is there.
Thanks for your help.
Jim
Comments
repeat while c == count
basically says - wait while the assembly language has not yet updated the sample.
The reason for doing this is that if the check was not there, then a sampled value could end up being used multiple times in the averaging process.
I understand the assembly code for this routine but I haven't quite figured out how the 'counter' variable in assembly gets passed back to the 'count' variable in the spin code.
I'll keep looking.
Thanks again.
is where it happen.
Initially t1 points to ins[noparse][[/noparse]0]
Every time around the loop (djnz t3,#cloop)·t1 gets incrmented by 2, so will point in turn to
ins[noparse][[/noparse]1/2], ins[noparse][[/noparse]1], ins[noparse][[/noparse]1 1/2], ins[noparse][[/noparse]2], ins[noparse][[/noparse]2 1/2], ins[noparse][[/noparse]3], ins[noparse][[/noparse]3 1/2].
Once it exists the loop, t1 will be pointing to count.
At that point the value of counter is written to the address pointed to by t1 - which is count in the spin code. And·counter is incremented·for next time.
Then the assembly code goes and does it all again.
·
I'm still learning the Propeller Assembly language, I'm almost there...
What fooled me here was that I assumed that the 'wrlong' command used the same syntax as most of the other instructions, i.e. right to left. Bad assumption! As soon as I saw that, everything fell into place.
Thanks again.
Jim
P.S. I think the people that write these routines should take credit for them by putting their name in the remarks at the top. This is a pretty amazing piece of code.
I'm having trouble understanding how a particular call to an assembly language routine works.
In the "startx" routine of MCP3208.spin there's a statement that says:
return cog := cognew(@entry, @ins) + 1
To me this says start a new assembly language cog with entry point @entry and parameter list at @ins. This all seems fine.
Below, there's the routine called "in", which returns the adc value to the caller:
PUB in(channel) : sample
'' Read the current sample from an ADC channel (0..7)
return ins.word[noparse][[/noparse]channel]
What I don't understand is that the last line looks like it is calling the routine "ins", which is the parameter list and not the entry point for the assembly code.
The manual doesn't seem to cover this. Can someone please explain?
Thanks for your help!
I've been agonizing over this routine (MCP3208.spin), trying to really understand it.
In the process I've been running timing tests by counting clock cycles to see how long it takes to get a sample and an average sample.
As a result, I think I discovered a bug in the program.
The sample average routine works great.
However, if you call the individual sample routine multiple times, you expect to get multiple readings from the chip.
This isn't what happens. Instead of returning a new sample value, it returns whatever is sitting in the last sample buffer.
This means if you call it 10 times you may well get the same old value each time, without it ever being updated.
The "in" routine is currently:
PUB in(channel) : sample
'' Read the current sample from an ADC channel (0..7)
return ins.word[noparse][[/noparse]channel]
Here's what I think it should be, to force an adc read whenever it's called:
PUB in(channel) : sample | c
c := count
repeat while c == count ' wait for new adc sample
'' Read the current sample from an ADC channel (0..7)
return ins.word[noparse][[/noparse]channel]
When I made this change and tested it, the timing was very close to that of the average routine for the same number of samples.
Would someone please take a look at this and let me know what you think?
Thanks for your help.
Jim