Why does this PASM code NOT work
Siri
Posts: 220
I am new to PASM and to assembly as a whole.
I am using a Propeller Proto Board and to it I have connected a ADC0831 to P0,P1 and P2 to ADC
Prop: PIN 0
> ADC pin 1 - chip select
PIN 1
> ADC pin 6 - Data Out
PIN 2
> ADC pin 7 - Clock
I also have pressure sensor connected to ADC - pin 2 - Vin and pin 3 - Gnd.V ref is connected to 5Vdc so is Vcc.
This set up works well with SPIN code flawlessly. (So hardware does work with no issues).I did this to make sure
that there is no hardware issues to deal with and the only troble shooting is with PASM code.
Here is the PASM code that does not work.
The display works as "Inapitarory pressure : 228" is displayed on the monitor.The decimal values do not get
updated when the pressure changes are made.(This works with SPIN Code).
So please help me to fix this and please explain in detail as much as possible - this will help me to understand
where I went wrong.
Thank you
Siri
I am using a Propeller Proto Board and to it I have connected a ADC0831 to P0,P1 and P2 to ADC
Prop: PIN 0
> ADC pin 1 - chip select
PIN 1
> ADC pin 6 - Data Out
PIN 2
> ADC pin 7 - Clock
I also have pressure sensor connected to ADC - pin 2 - Vin and pin 3 - Gnd.V ref is connected to 5Vdc so is Vcc.
This set up works well with SPIN code flawlessly. (So hardware does work with no issues).I did this to make sure
that there is no hardware issues to deal with and the only troble shooting is with PASM code.
Here is the PASM code that does not work.
The display works as "Inapitarory pressure : 228" is displayed on the monitor.The decimal values do not get
updated when the pressure changes are made.(This works with SPIN Code).
So please help me to fix this and please explain in detail as much as possible - this will help me to understand
where I went wrong.
The ADC is connected to propeller PINS : ADC_CS = 0 ' CS Pin connected to Propeller P0 ADC_Data = 1 ' Data Pin connected to Propeller P1 ADC_CLK = 2 'Clock Pin connected to Propeller P2 using a ADC0831 - chip } con _clkmode = xtal1 + pll16x ' _xinfreq = 5_000_000 ' VAR long Data Byte Exp long DisplayStack[noparse][[/noparse]80] obj Text : "VGA_Text" PUB start text.start(16) cognew(DisplayText,@DisplayStack) cognew(@entry,@Data) PUB DisplayText text.out($0D) text.str(string("Inspiratory pressure:")) repeat Exp :=(Data-115)/4 text.str(string($A,21,$B,1)) text.str(string(" ")) text.dec(Exp) DAT entry org 0 mov Insp, par 'Retrieve Data memeory addr Initialize mov ClockPinMask, #1 wz 'Configure Output pin shl ClockPinMask, ClockPin 'Create mask with ClockPin andn outa, ClockPinMask 'Preset Output Pin LOW "0" or dira, ClockPinMask 'Set pin as Output "1" mov DataPinMask, #1 wz 'Configure Input pin shl DataPinMask, DataPin 'Create mask with DataPin andn dira, DataPinMask 'Set pin as Input "0" mov CSPinMask, #1 wz 'Configure CS pin shl CSPinMask, CSPin 'Creaste mask with CSPin or dira, CSPinMask 'Set CSPin as Output SHIFTIN mov DataBitMask, #1 'Create BitMask shl DataBitMask, DataBits 'Set number of Bits mov _Data, #0 'Clear Data _ReadNextBit andn outa, CSPin 'Set CSPin LOW - select chip or outa, ClockPinMask 'Set Clock pin HIGH - Start Clock test DataPinMask, ina wc 'Load "C" with DataPin value -set C flag muxc _Data, DataBitMask 'Move "C" into Data via DataBitMask position andn outa, ClockPinMask 'Set Clock pin LOW - End Clock shr DataBitMask, #1 wz 'Move BitMask position right by 1 ' if_nz jmp #_ReadNextBit 'Jump to '_ReadNextBit' if there are more bits or outa, CSPinMask 'Deselect - set CSpin High wrlong _Data, Insp 'write Cog variable value _Data to HUB variable address Data 'via Insp COG vaiable ClockPin long 2 'Define I/O Clock Pin DataPin long 1 'Define I/O Data Pin DataBits long 7 'Set number of Data Bits ( N = Bits - 1 = [noparse][[/noparse]0 to 31] ) CSPin long 0 'Chip select pin ClockPinMask res 1 'ClockPin Mask DataPinMask res 1 'DataPin Mask DataBitMask res 1 'Data Mask CSPinMask res 1 'CSPin Mask _Data res 1 'Holds result value from SHIFTIN Insp res 1 'holds the address of Data
Thank you
Siri
Comments
1.mov·······ClockPinMask,···········#1········wz······ and other occurances of this, there is no need for the wz since you are not setting it, it doesn't cause an error but confusing when reading the code
2.··············or·······dira,····················CSPinMask···········'Set·CSPin·as·Output
you dont preset the outa value to 1 which you should before setting CS as output
3.ReadNextBit··andn·····outa,····················CSPin···············'Set·CSPin·LOW·-·select·chip
Since you never change CSPin within the loop, you can move the ReadNextBit to the next instruction
4.···············wrlong···_Data,···················Insp············'write·Cog
After this instruction is run the code runs whatever happens to be in memory, which I doubt is what you want. I expect you want to repeat the loop from SHIFTIN, so you need a jmp #SHIFTIN to do that
I would guess the code will run without 1,2 and 3 but 4 will cause it to run once and stop.
Thanks for the quick reply.
I made the changes you suggested but the code still does not work right.
All I see on the Display is "Inspiratory pressure: 228"
The pressure value is not updated when prssure is increased.Even after adding the last code line- " jmp#SHIFTIN"
Thanks
Siri
On a serious note: The maximum clock for the ADC0831 is 400 kHz, so 2.5 us per clock cycle, your loop has a cycle of 6*4*0.0125= 0.3 us... i.e. it is too fast.
Second: as per the datasheet you have to read 10 bits to get the 8 MSBs of your conversion (page 3 of the texas datasheet found on alldatasheet.com).
Third : All the comments timmoore did.
Have fun
Ale
Thank you very much.
The ADC I am using is a"National Semiconductor product" it is 8 bit convertor.I have attached the specs for you to see
as I am not an electronic gut to digest all the details - How fast/clock cycles etc.
Please refer to it and help me to resolve this.
As for "Inspiratory pressure" - it the pressure generated while a person takes breath- inspire.I am working on a
Mechanical Ventilator - breathing machine.- for a noble cause.
Thanks once again
Siri
1. From cs low to clk is Tsetup of 250ns, with a 80Mhz prop clock that is 5 instructions. So there needs to be 5 instructions between taking cs low and changing clk. If not insert 1 or more nops to get 5 instructions
2.Looks like MSB bit is output on the 2nd clk, not the first (see page 9 diagram).
3. data is output Tpd0 from falling edge of clk, so you need to read data in 1500ns after taking clk low, thats 30 instructions.
4. you need to generate 10 clks to get the data, the first and last clk dont generate actual data but diagram on 9 shows them
5. The max clk speed is 400Khz, or 2500ns for time for 1 clk period. You need to speed 1500ns with clk low (3). so you need to speed 1000ns or 20 instructions with the clk high.
When you are writing in ASM you are running fast enough that the detailing timings in the data sheet matter. With Spin you tend to be slow enough that the minimum timings dont matter (though I have seen cases of max timing that cause problems with spin, but thats uncommon).
So I would add nops in places to get the right time delay. Then change the datamask to start at the 10th bit rather than 8th bit/ After getting all 10 bits but before writing it (wrlong), shift the data 1 bit to the right. That removes the last bit you read.
I think I have made all the changes you sugested.I also hasve the PDF specs and can see exactly what you
are doing with the timing.
I am still unable to get this code to work.
Here is the modified code:
Also you read after to set the clk high, I read the datasheet as the data available when the clk goes low (+ tpd0 time). So you are reading on the wrong clk edge and you are not allowing the right amount of time.
The best way is to go through your _readnextbit loop, for each instruction plot the clk value and mark when you read data. Write how long between each change of clk and when you read and compare it with the data sheet. 1 prop instruction is 50ns for a 80Mhz clk.
Once you have the readnextbit loop timing correct. Then plot the same for the shiftin loop, looking for number of bits you are reading and again comparing with teh datasheet timing diagrams.
I will do all that and will get back.
I do appreciate all what you are doing to get this code to work and also teaching me.
Regards,
Siri
A good way to wait is to use the waitcnt instruction:
[noparse][[/noparse]code]
andn OUTA,CSpin
nop
nop
nop
nop
nop
mov futurecnt, CNT
add futurecnt, hicycle ' tsu = 350 ns
_ReadNextBit
or outa, ClockPinMask 'Set Clock pin HIGH - Start Clock
nop
nop ' hold time till data valid = 90 ns
test DataPinMask, ina wc 'Load "C" with DataPin value -set C flag
muxc _Data, DataBitMask 'Move "C" into Data via DataBitMask position
shr _Data, #1
waitcnt futurecnt, locycle ' waits the the rest high cycle period
andn outa, ClockPinMask 'Set Clock pin LOW - End Clock
waitcnt futurecnt, hicycle
shr DataBitMask, #1 wz 'Move BitMask position right by 1 '
if_nz jmp #_ReadNextBit 'Jump to '_ReadNextBit' if there are more bits
andn outa, CSPinMask 'Set CSPin as Output
wrlong _Data, Insp 'write Cog variable value _Data to HUB variable address Data
jmp #SHIFTIN 'jump to SHIFTIN to read next Data byte
locycle long 80
hicycle long 80 ' adjust this two to have a 2.5 us cycle period, each waitcnt takes at least 6 cycles
futurecnt long 0
that may work
Tim,
I added "witcnt" to both loops which I caculated out from the spec sheets.Then I tried changing the "waitcnts"
up and down trying find a correct timing.So far no luck.
Ale,
I will try your suggestions and let you know.
Thanks to both of you
Regards,
Siri
I tried what both of you suggested changed the Delay times trying to find right delay.I re-calculated the timings
few times.I have come to the conclusion that I need another strategy - so I am going to get out the scope and
try to get the timings correct.
I would like to hear your thoughts and advise.
Thanks,
Regards,
Siri
Still trying- Thre seem to be a DATA aquisition problem - The Clock high to high cycle seems OK.
Attached are 4 scope tracings 2 from the working "SPIN code" and 2 from the rogue "PASM code"
I hope this will give you more insight to the issue to get this resolved.
Regards,
Siri
I will try to send it again.
If not here is the data: Amost a flat base line tracing.
Max Voltage:230mV
Min Voltage:0mV
Peak to Peak:230mV
true RMS Voltage:82mV - Mean Voltage : 80mV
Frequency: 7.9KHz
Period: 126uS
Siri
Can you also post your latest code.
I think I made boo boo - The clock pin tracings were not correct.- wrong connections.
Attached are the 2 tracings from the ClockPin of ADC.
Sorry for that.
There seem to be NO clock signal with PASM code.
Regards,
Siri
The other thing is the cs pin control doesn't look right, I dont think its going high and low correct - sometimes you set dira and sometimes outa the effect together probably isn't what you want.
You havbe 2 separate problems 1. getting the timing right and 2 getting the algoithm correct. I find getting the algorithm right is best done with a best of paper and drawing the highs/lows as you step by hand through the code. Do 1 instruction at a time, dont skip assuming you know what will happen, write down the value of each variable and input. Once you are confident of the algorithm then look at the timing.
I am trying to get my PASM code right. I am not really clear - correct way to set a PIN - HIGH/LOW and the direction Input/Output.
That is do I set the dira register FIRST and then the OUTA register or the other way round OUTA first and then dira second.
In spin DIRA register seem to be set first and then the OUTA register(That is how it is set in the SPIN SHIFTIN routine I am using now with this setup)
DO I have to set BOTH registers all the time. If not what conditions dictate when to do what?
Thanks,
Regards
Siri
I recommend setting a cog's OUTA bit first so, if the I/O pin is initially in input mode, the state of the I/O pin will be known when the cog sets its DIRA bit to 1 as well.
When making a pin output, set outa then dira. After than just set outa.
When setting a pin to put just reset the relevant pin of dira
I normally use or/andn instruction pair or muxc instruction to set/reset pins either for outa or dira though other combinations work.
Thanks for the quick reply.
Now I will get down to solve my coding issues.
Regards,
Siri
I have done my code over and over but I am unable to get any data out to the display(VGA)
Here is the code , I had some success - This will CS pin out put on the scope which is
smiler to the one I get with the SPIN code but no data or clock signal tracings.
A new problem has come about - thai It takes about 45- 50 sec for the tracing to show up on
the scope.
I remember reading about missing the access to the HUB and hence takes about 59 sec to catch
up again.
If this is the case where is it happening .Is it at the Delay/wait parameters?
Thanks for the help and patience.
Regards,
Siri
I have attached a modified file, that puts the delays in the places that the datasheet wants - I comment them with Tsetup, Tpd0, etc that the datasheet calls them. Take a look and see if you understand why I moved them to those places. I also changed when you read the data, the datasheet says the data is valid 1500ns after the falling edge of the clock, not the rising edge.
Thanks a lot.
I loaded your program and it worked.Now I need to digest the reasons for the change.
Tim - I like your style - I know you could have just posted the correct code but that would
not have taught much as far as understanding the problem.
I will get back to you If I need further explanation.
Regards,
Siri
Now that capturing the digital output from the ADC is resolved - I have uncovered another concerning thr digital out-put.
The digital output when using SPIN code - the range is : 9- 255 - a small zero error
The digital output when using PASM code - the range : 235 - 255 ????
What is the problem and what is the solution to this.
From what I understand the ADC0831 - digital range is: 0 - 255 .The pressure transducers out-put is ratiometric 0-4v.
I would like to see PASM digital range to be close or like SPIN range.
Regards,
Siri
I did what you recomended adding "0" to make the DataBitMask to #%10_000_000_000 this brigs the error "Source rgister/
constant cannot exeed $1FF. - I do understand why so I scaled it back to %1_000_000_000.
Then I played with these inatructions : 1. shr _data #1 ----> Readinggs - start 252 - end 192
2. and _Data #ff
> start 242 - end 255
Then I commented out these 2 instructions: 1. shr _Data #1
2. and _Data #ff
Now I get exact range of the pressure sensor 0 to 30 inches of pressure - after converting volts/pressure.
Thanks again,
Regards
Siri
Here is the last code that worked corrctly:
Post Edited (Siri) : 10/12/2008 3:35:22 PM GMT
mov DataBitMask, #%100000000
by adding
shl DataBitMask, #1
after it to get you the 10 bits of reading
I went through the specs of ADC0831 but did not see any thing to that effect.Anyway I tried changing the code to see what happens.It did
shoe values but they were 90 t0 125 - not the correct values.
Thank you very much for helping/teaching me.
Regards,
Siri