Can I get some advice on modifying the Rotary Encoder object?
A main program launches a PID engine cog which launches this Rotary object.
When the rotary object is launched, it clears the position of all encoders to zero. I am only using one encoder, possibly 2 as an option. I need to be able to set the position of the encoder by the top program. I tried setting a value to the variable that the Position is stored in, but it gets written back to zero on launching the PASM. I can live with the idea of setting the value on launching the engine. There are cases where on bootup, the encoder is in a position that I don't want to be zero.
Any help would be greatly appreciated.
When the rotary object is launched, it clears the position of all encoders to zero. I am only using one encoder, possibly 2 as an option. I need to be able to set the position of the encoder by the top program. I tried setting a value to the variable that the Position is stored in, but it gets written back to zero on launching the PASM. I can live with the idea of setting the value on launching the engine. There are cases where on bootup, the encoder is in a position that I don't want to be zero.
Any help would be greatly appreciated.
VAR
byte Cog 'Cog (ID+1) that is running Update
byte TotDelta 'Number of encoders needing deta value support.
long Pos 'Address of position buffer
PUB Start(StartPin, NumEnc, NumDelta, PosAddr, direction): Pass
''Record configuration, clear all encoder positions and launch a continuous encoder-reading cog.
''PARAMETERS: StartPin = (0..63) 1st pin of encoder 1. 2nd pin of encoder 1 is StartPin+1.
'' Additional pins for other encoders are contiguous starting with StartPin+2 but MUST NOT cross port boundry (31).
'' NumEnc = Number of encoders (1..16) to monitor.
'' NumDelta = Number of encoders (0..16) needing delta value support (can be less than NumEnc).
'' PosAddr = Address of a buffer of longs where each encoder's position (and deta position, if any) is to be stored.
''RETURNS: True if successful, False otherwise.
Pin := StartPin
TotEnc := NumEnc
TotDelta := NumDelta
Pos := PosAddr
Stop
SetDir(direction)
longfill(Pos, 0, TotEnc+TotDelta)
Pass := (Cog := cognew(@Update, Pos) + 1) > 0
PUB SetEncoder
PUB SetDir(direction)
if direction == 1 'Subtract
AMask[-8] |= |< 26 ' sub set bit 26 high fr subtract = reverse counting
elseif direction == 0 'Add
AMask[-8] &= !|< 26 ' add bitwise NOT bit 26 of the :IPos add 0, Diff
PUB Stop
''Stop the encoder-reading cog, if there is one.
if Cog > 0
cogstop(Cog~-1)
PUB ReadDelta(EncID): DeltaPos
''Read delta position (relative position value since last time read) of EncID.
DeltaPos := 0 + -(EncID < TotDelta) * -long[Pos][TotEnc+EncID] + (long[Pos][TotEnc+EncID] := long[Pos][EncID])
'************************************
'* Encoder Reading Assembly Routine *
'************************************
DAT
'Read all encoders and update encoder positions in main memory.
'See "Theory of Operation," below, for operational explanation.
'Cycle Calculation Equation:
' Terms: SU = :Sample to :Update. UTI = :UpdatePos through :IPos. MMW = Main Memory Write.
' AMMN = After MMW to :Next. NU = :Next to :UpdatePos. SH = Resync to Hub. NS = :Next to :Sample.
' Equation: SU + UTI + MMW + (AMMN + NU + UTI + SH + MMW) * (TotEnc-1) + AMMN + NS
' = 92 + 16 + 8 + ( 16 + 4 + 16 + 6 + 8 ) * (TotEnc-1) + 16 + 12
' = 144 + 50*(TotEnc-1)
org 0
Update test Pin, #$20 wc 'Test for upper or lower port
muxc :PinSrc, #%1 'Adjust :PinSrc instruction for proper port
mov IPosAddr, #IntPos 'Clear all internal encoder position values
movd :IClear, IPosAddr ' set starting internal pointer
mov Idx, TotEnc ' for all encoders...
:IClear mov 0, #0 ' clear internal memory
add IPosAddr, #1 ' increment pointer
movd :IClear, IPosAddr
djnz Idx, #:IClear ' loop for each encoder
mov St2, ina 'Take first sample of encoder pins
shr St2, Pin
:Sample mov IPosAddr, #IntPos 'Reset encoder position buffer addresses
movd :IPos+0, IPosAddr
movd :IPos+1, IPosAddr
mov MPosAddr, PAR
mov St1, St2 'Calc 2-bit signed offsets (St1 = B1:A1)
mov T1, St2 ' T1 = B1:A1
shl T1, #1 ' T1 = A1:x
:PinSrc mov St2, inb ' Sample encoders (St2 = B2:A2 left shifted by first encoder offset)
shr St2, Pin ' Adj for first encoder (St2 = B2:A2)
xor St1, St2 ' St1 = B1^B2:A1^A2
xor T1, St2 ' T1 = A1^B2:x
and T1, BMask ' T1 = A1^B2:0
or T1, AMask ' T1 = A1^B2:1
mov T2, St1 ' T2 = B1^B2:A1^A2
and T2, AMask ' T2 = 0:A1^A2
and St1, BMask ' St1 = B1^B2:0
shr St1, #1 ' St1 = 0:B1^B2
xor T2, St1 ' T2 = 0:A1^A2^B1^B2
mov St1, T2 ' St1 = 0:A1^B2^B1^A2
shl St1, #1 ' St1 = A1^B2^B1^A2:0
or St1, T2 ' St1 = A1^B2^B1^A2:A1^B2^B1^A2
and St1, T1 ' St1 = A1^B2^B1^A2&A1^B2:A1^B2^B1^A2
mov Idx, TotEnc 'For all encoders...
:UpdatePos ror St1, #2 'Rotate current bit pair into 31:30
mov Diff, St1 'Convert 2-bit signed to 32-bit signed Diff
sar Diff, #30
' add or substraction the count to the accumulator
:IPos add 0, Diff 'AMask[-8] ****Add/Sub to encoder position value
wrlong 0, MPosAddr 'Write new position to main memory
add IPosAddr, #1 'Increment encoder position addresses
movd :IPos+0, IPosAddr
movd :IPos+1, IPosAddr
add MPosAddr, #4
:Next djnz Idx, #:UpdatePos 'Loop for each encoder
jmp #:Sample 'Loop forever
'Define Encoder Reading Cog's constants/variables
AMask long $55555555 'A bit mask
BMask long $AAAAAAAA 'B bit mask
MSB long $80000000 'MSB mask for current bit pair
Pin long 0 'First pin connected to first encoder
TotEnc long 0 'Total number of encoders
Idx res 1 'Encoder index
St1 res 1 'Previous state
St2 res 1 'Current state
T1 res 1 'Temp 1
T2 res 1 'Temp 2
Diff res 1 'Difference, ie: -1, 0 or +1
IPosAddr res 1 'Address of current encoder position counter (Internal Memory)
MPosAddr res 1 'Address of current encoder position counter (Main Memory)
IntPos res 16 'Internal encoder position counter buffer
''
''
''**************************
''* FUNCTIONAL DESCRIPTION *
''**************************
''
''To use this object:
'' 1) Create a position buffer (array of longs). The position buffer MUST contain NumEnc + NumDelta longs. The first NumEnc longs of the position buffer
'' will always contain *****read-only*****, absolute positions for the respective encoders. The remaining NumDelta longs of the position buffer will be "last
'' absolute read" storage for providing delta position support (if used) and should be ignored (use ReadDelta() method instead).

Comments