Assembler Question

I'm using Mr. Schwabs PWM object http://obex.parallax.com/objects/467/ and I'm trying add the following logic to the assembler section (Main_PWM_Loop):
If P8 = 1 let the assembly modify Pins 13 thru 15 normally.
But, if P8=0 then set Pins 13 thru 15 to Zero.
I need to integrate it into the same cog. But, I'm not sure how I can accomplish said task?
... Tim
If P8 = 1 let the assembly modify Pins 13 thru 15 normally.
But, if P8=0 then set Pins 13 thru 15 to Zero.
I need to integrate it into the same cog. But, I'm not sure how I can accomplish said task?
... Tim
Comments
test mask8, ina wc if_nc andn temp, mask13_15
This code could then be placed just before the update for outa. Or you do the P8 test before temp is initialised and simply gate your bit updates with a condition:test mask8, ina wc mov temp, Ch + 00 ... if_c or temp, Ch + 13 if_c or temp, Ch + 14 if_c or temp, Ch + 15 or temp, Ch + 16 ...
Is that what you are after?Yes ... Very, Very, Very close to the target!!!
Thankyou so much!
In keeping with one of the earlier post's regarding 'solutions' ... when I get the answer, I'll post the solution.
... Tim
'' Update IO Pins mov temp, Ch + 00 ' Clear and initialize temp or temp, Ch + 01 ' OR the remaining or temp, Ch + 02 ' channels into temp <trimmed for space> or temp, Ch + 08 test Ch + 08, #0 wz <trimmed for space> if_nz or temp, Ch + 13 if_nz or temp, Ch + 14 if_nz or temp, Ch + 15 mov outa, temp ' Move temp to the IOs
Now I just need to figure out what the timing constant changes too?''Resolution Resolution = 8200
Would it be 8204?... Tim
As for the period, the main loop - when running uninterrupted consumes exactly 41 hub windows (16*32+4*32+4+12 = (40+1)*16, 656*12.5 = 8200). So you could either raise it to 8400 (since you're adding 1 hub window, 16*12.5) or move the or temp, Ch + 08 to the front (swap with Ch + 00, i.e. mov temp, Ch + 08 wz) and grab the flag state without timing penalty (8200).
Also, I was unaware the the Zero flag would be set in that test d,s for all case's the Propeller manual PDF says:
Thanks for the clarification and the calculation:
... Tim
'' Update IO Pins mov temp, Ch + 08 wz ' Clear and initialize temp or temp, Ch + 00 or temp, Ch + 01 ' OR the remaining or temp, Ch + 02 ' channels into temp or temp, Ch + 03 or temp, Ch + 04 or temp, Ch + 05 or temp, Ch + 06 or temp, Ch + 07 or temp, Ch + 09 or temp, Ch + 10 or temp, Ch + 11 or temp, Ch + 12 if_nz or temp, Ch + 13 if_nz or temp, Ch + 14 if_nz or temp, Ch + 15 or temp, Ch + 16 or temp, Ch + 17 or temp, Ch + 18 or temp, Ch + 19 or temp, Ch + 20 or temp, Ch + 21 or temp, Ch + 22 or temp, Ch + 23 or temp, Ch + 24 or temp, Ch + 25 or temp, Ch + 26 or temp, Ch + 27 or temp, Ch + 28 or temp, Ch + 29 or temp, Ch + 30 or temp, Ch + 31 mov outa, temp ' Move temp to the IOs
Thanks for all your help, here is where that code went:
pin 8 drives my FIELD switch and pins 13, 14 and 15 are the 3 phase signal used to drive motor with.
Because of the way the IGBT's get power, I have to turn the bottom switch on now and then to charge the 1000 uF cap that powers the top IGBT boards (6 in all, 3 top and 3 bottom).
Due to construction an output on pin 13-15 of 0, turns on the bottom switch ... and outputing a '1' turns the top switch on. changing the dira to input on any of these pins, prevents either switch from operating!
... Tim
OK, next stupid question ... Is there an easy way to calculate modulo in assembly?
... Tim
It depends on the divisor. 2^N is a simple AND. Some other constant values can be calculated by a sequence of shifts, adds and subtracts. Other otherwise it's a modified divide routine.
Well, maybe that's the wrong approach ... maybe the question should be:
Is there a way to read the motor encoder and create a pattern like this:
vctr count 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1/2 turn enc ticks 14 14 14 15 14 14 14 14 15 14 14 14 15 14 14 14 14 15 mod 4/mod 5 space vctr 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 mod 6 The above table shows 1/2 half shaft revolution. And adds up to 256 ticks, since there are 512 in complete circle, you must travel thru the 6 vectors six times before the shaft turns once.
... TimOK ... so
57 mod 9
could be done by:
%111001 = 57 - %100100 = 36 9 << 2 ------------------ %010101 = 21 - %010010 = 18 9 << 1 ------------------ %000011 = 3
... TimYou mean out of this entire forum ... none of you have a modulus routine in assembly? (shaking the tree, as it were)
... Tim
I was able to replace a modulus routine in assembler by putting my bit pattern repeated in a long and then using ROL for 1 direction and ROR for the reverse direction. My pattern was a 4 bit pattern and I did a ROL,#4 then transfered the new pattern to a temp variable and then anded %1111 with it to get the necessary pattern. SHL,BasePin then moves it to the correct output..
Jim
Thankyou for the feed back .... do you have a example piece of code lying about I might be able to look at?
... Tim
' Divide x[31..0] by y[15..0] (y[16] must be 0) ' on exit, quotient is in x[15..0] and remainder is in x[31..16] ' divide shl y,#15 'get divisor into y[30..15] mov t,#16 'ready for 16 quotient bits :loop cmpsub x,y wc 'y =< x? Subtract it, quotient bit in c rcl x,#1 'rotate c into quotient, shift dividend djnz t,#:loop 'loop until done divide_ret ret 'quotient in x[15..0], '[COLOR="orange"]remainder in x[31..16][/COLOR]
I didn't catch that! Thank you!
I got the motor to run today using a spin version of my Idea ... but it does not go very fast.
case (Shaft & $FF) 000..013: outa := SV[0] 014..027: outa := SV[1] 028..041: outa := SV[2] 042..056: outa := SV[3] 057..070: outa := SV[4] 071..084: outa := SV[5] 085..098: outa := SV[0] 099..112: outa := SV[1] 113..127: outa := SV[2] 128..141: outa := SV[3] 142..155: outa := SV[4] 156..169: outa := SV[5] 170..184: outa := SV[0] 185..198: outa := SV[1] 199..212: outa := SV[2] 213..226: outa := SV[3] 227..240: outa := SV[4] 241..255: outa := SV[5]
And, this is what I think is close to same?DAT SV_Asm org loop1 and Shaft, #$FF ' mask unused bits cmp Shaft, #14 wc if_c mov SV_Index,#0 if_c jmp set_vector cmp Shaft, #28 wc if_c mov SV_Index,#1 if_c jmp set_vector cmp Shaft, #42 wc if_c mov SV_Index,#2 if_c jmp set_vector cmp Shaft, #57 wc if_c mov SV_Index,#3 if_c jmp set_vector cmp Shaft, #71 wc if_c mov SV_Index,#4 if_c jmp set_vector cmp Shaft, #85 wc if_c mov SV_Index,#5 if_c jmp set_vector cmp Shaft, #99 wc if_c mov SV_Index,#0 if_c jmp set_vector cmp Shaft, #113 wc if_c mov SV_Index,#1 if_c jmp set_vector cmp Shaft, #128 wc if_c mov SV_Index,#2 if_c jmp set_vector cmp Shaft, #142 wc if_c mov SV_Index,#3 if_c jmp set_vector cmp Shaft, #156 wc if_c mov SV_Index,#4 if_c jmp set_vector cmp Shaft, #170 wc if_c mov SV_Index,#5 if_c jmp set_vector cmp Shaft, #185 wc if_c mov SV_Index,#0 if_c jmp set_vector cmp Shaft, #199 wc if_c mov SV_Index,#1 if_c jmp set_vector cmp Shaft, #213 wc if_c mov SV_Index,#2 if_c jmp set_vector cmp Shaft, #227 wc if_c mov SV_Index,#3 if_c jmp set_vector cmp Shaft, #241 wc if_c mov SV_Index,#4 if_c jmp set_vector mov SV_Index,#5 ' last vector Set_Vector mov outa, SV_Index jmp #loop1 Shaft long 0 SV_Index long 0
Maybe there is a better way to preform 'case' in assembly? Any Ideas?... Tim
and Shaft, #$FF cmp Shaft, #227 if_nc jmp #:l227-255 cmp Shaft, #56 if_nc jmp #:l57-112 :l0-56 cmp Shaft, #28 wc if_nc jmp #:l28-56 :l0-27 cmp Shaft, #14 wc if_c mov SV_Index, #0 if_nc mov SV_Infex, #1 jmp set_vector :l28-56 cmp Shaft, #42 wc if_c mov SV_Index, #2 if_nc mov SV_Index, #3 jmp set_vector :l57-112 cmp Shaft, #85 wc if_nc jmp #:l85-112 :l57-84 cmp Shaft, #71 wc if_c mov SV_Index, #4 if_nc mov SV_Index, #5 jmp set_vector :l85-112 cmp Shaft, #99 wc if_c mov SV_Index, #0 if_nc mov SV_Index, #1 jmp set_vector 113..127: outa := SV[2] 128..141: outa := SV[3] 142..155: outa := SV[4] 156..169: outa := SV[5] 170..184: outa := SV[0] 185..198: outa := SV[1] 199..212: outa := SV[2] 213..226: outa := SV[3] :l227-255 cmp Shaft, #241 if_c mov SV_Index, #4 if_nc mov SV_Index, #5 set_vector
Thank you very much for your reply!
First, I understand what you mean by binary tree to divide your outputs. And I'm not sure why I didn't see that before? I guess I can't see the forest for the tree's.
Second, I do not understand what you mean by dereference SV_Index? After all, this is my first attempt at putting together a assembly driver! Could you explain for me please!
... Tim
There are a few different ways to handle what you want to do. Easiest is probably something like:
:l85-112 cmp Shaft, #99 wc if_c mov outa, SV_0 if_nc mov outa, SV_1 jmp set_vector SV_0 long $0000_1000 SV_1 long $0000_2000
1st thanks for all the help!
But, I'm now having an issue with PASD ... I am able to single step through the example that came with it, but not my own code? I've double checked that I have kernel copied correctly (and no, no char's are at column 0) ... and after reading through some of the old post's that got deleted, discovered that you can not have a CON section following your code ... I'm ok there too, nothing follows my DAT section.
I've included a copy of code here. Any ideas?
DAT org 0 entry ' --------- Debugger Kernel add this at Entry (Addr 0) --------- long $34FC1202,$6CE81201,$83C120B,$8BC0E0A,$E87C0E03,$8BC0E0A long $EC7C0E05,$A0BC1207,$5C7C0003,$5C7C0003,$7FFC,$7FF8 ' -------------------------------------------------------------- SV_Asm mov temp, par mov outa, #0 mov dira, Mask_Mtr mov cmd_address, temp 'Acquire command variable address add temp, #4 mov ARG_0, temp 'Acquire ARG_0 variable address add temp, #4 mov ARG_1, temp 'Acquire ARG_1 variable address add temp, #4 mov ARG_2, temp 'Acquire ARG_2 variable address rdlong Pntr0, ARG_0 rdlong Pntr1, ARG_1 rdlong Pntr2, ARG_2 Main_Loop rdlong SV_Duty,Pntr2 ' read duty control rdlong SV_Offset,Pntr1 ' read offset rdlong Shaft, Pntr0 ' read from motor encoder position ' comment-out the line below to remove hard coded pin reversal. neg Shaft, Shaft ' negate reading max SV_Duty, #5 ' hard code limit! mov Mask_t, Mask_duty shr Mask_t, SV_Duty mov cnt, cnt mov temp, cnt shr temp, Clk_Shft and temp, Mask_t wz ' zero flag = turn field "ON" if_nz andn dira, Mask_f ' turn field OFF if_nz mov outa, Zero ' zero motor pins if_nz jmp #Cmd_Chk add Shaft, SV_Offset and Shaft, #$FF ' mask unused bits cmp Shaft, #170 wc if_nc jmp #:l3 cmp Shaft, #85 wc if_nc jmp #:l2 '------------------------------------------------------------- cmp Shaft, #14 wc if_c mov SV_Index,SV_0 if_c jmp set_vector cmp Shaft, #28 wc if_c mov SV_Index,SV_1 if_c jmp set_vector cmp Shaft, #42 wc if_c mov SV_Index,SV_2 if_c jmp set_vector cmp Shaft, #57 wc if_c mov SV_Index,SV_3 if_c jmp set_vector cmp Shaft, #71 wc if_c mov SV_Index,SV_4 if_c jmp set_vector ' cmp Shaft, #85 wc mov SV_Index,SV_5 jmp set_vector '------------------------------------------------------------- :l2 nop nop cmp Shaft, #99 wc if_c mov SV_Index,SV_0 if_c jmp set_vector cmp Shaft, #113 wc if_c mov SV_Index,SV_1 if_c jmp set_vector cmp Shaft, #128 wc if_c mov SV_Index,SV_2 if_c jmp set_vector cmp Shaft, #142 wc if_c mov SV_Index,SV_3 if_c jmp set_vector cmp Shaft, #156 wc if_c mov SV_Index,SV_4 if_c jmp set_vector ' cmp Shaft, #170 wc mov SV_Index,SV_5 jmp set_vector '------------------------------------------------------------- :l3 nop nop nop nop cmp Shaft, #185 wc if_c mov SV_Index,SV_0 if_c jmp set_vector cmp Shaft, #199 wc if_c mov SV_Index,SV_1 if_c jmp set_vector cmp Shaft, #213 wc if_c mov SV_Index,SV_2 if_c jmp set_vector cmp Shaft, #227 wc if_c mov SV_Index,SV_3 if_c jmp set_vector cmp Shaft, #241 wc if_c mov SV_Index,SV_4 if_c jmp set_vector mov SV_Index,SV_5 ' last vector '------------------------------------------------------------- Set_Vector mov outa, SV_Index mov temp, Mask_Mtr or temp, Mask_F or dira, temp '------------------------------------------------------------- ''Command Detected ; Check for valid Commands Cmd_Chk rdlong temp, cmd_address mov cmd, temp shr cmd, #24 wz if_z jmp #Main_Loop xor cmd, #SetReverse wz,nr if_z jmp #Rev_Encoder xor cmd, #SetShift wz,nr if_z jmp #Set_Shift wrlong Zero, cmd_address jmp #Main_Loop '------------------------------------------------------------- '' SetReverse code Rev_Encoder ' not coded yet! wrlong Zero, cmd_address jmp #Main_Loop Set_Shift mov Clk_Shft, temp and Clk_Shft, #$FF wrlong Zero, cmd_address jmp #Main_Loop Shaft long 0 SV_Offset long 0 SV_Index long 0 SV_Duty long 0 Clk_Shft long 18 Mask_t long 0 Cmd long 0 temp long 0 Zero long 0 cmd_address long 0 ARG_0 long 0 ARG_1 long 0 ARG_2 long 0 Pntr0 long 0 Pntr1 long 0 Pntr2 long 0 Mask_Duty long %0111_1111 Mask_Mtr long %111 << MotorPin Mask_f long %1 << FieldPin ' PPDB pins SV_0 long %001 << MotorPin + 1 << FieldPin SV_1 long %011 << MotorPin + 1 << FieldPin SV_2 long %010 << MotorPin + 1 << FieldPin SV_3 long %110 << MotorPin + 1 << FieldPin SV_4 long %100 << MotorPin + 1 << FieldPin SV_5 long %101 << MotorPin + 1 << FieldPin { ' Proto Board pins SV_0 long %01_01_10 << MotorPin + 1 << FieldPin SV_1 long %01_10_10 << MotorPin + 1 << FieldPin SV_2 long %01_10_01 << MotorPin + 1 << FieldPin SV_3 long %10_10_01 << MotorPin + 1 << FieldPin SV_4 long %10_01_01 << MotorPin + 1 << FieldPin SV_5 long %10_01_10 << MotorPin + 1 << FieldPin }
1st, your correct that @SV_Asm is passed to cognew. But, that only happens if I press the 'PLAY' button on my remote (see Install_Motor method)! In the debug version ... @entry is passed. However, I think you pointed me in the right direction ... my assembly start routine passes the @command spin var as a second variable in the cognew command, but in the debug cognew, that doesn't happen!
Is that a problem? Because the first 'step' in PASD is mov temp, par and nothing has been passed! And, that is the instruction that 'crashes' the PASD session!
2nd, what do you mean by "ord'd incorrectly"?
3rd, why don't I want to use jmp set_vector?
... Tim
PS - still learning!
Well, you start the DAT block with org 0 which is followed by the debug kernel. Those 12 longs push your program back so you can't run it as if it were located at 0 (which is what your cognew would do). In English, all the address references are wrong.
The current form is an indirect jump. It takes the content of set_vector (mov outa, SV_Index) and uses the lower 9 bits as a jump target. The source field contains the address of SV_index which is $07B (with debug kernel). If you want to jump to the set_vector label use the direct form (jmp #set_vector).
I can't believe I missed that!!!!!! After all the reading & studying ... but after that change, the driver started working! My first assembly driver (well, it's actually 90% owed to you and this forum!) and the motor turns correctly!
Thank you so much for your input!!! Still one more challenge to over come, but that's down hill from where I am now! Need to come up with a method to detect the best acceleration for any given offset value? With the remote, I can change the offset by pressing '7' or '9' on the remote (by 16) and also by pressing the 'up' or 'down' arrow keys (by one).
Since the motor driver can be installed at any shaft position (detected by E4P object), the offset that best moves the motor in your desired direction must be found!
... Tim