This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS570LC4357: How to properly set up the SWAG?

Part Number: TMS570LC4357


Hello, I've been fighting with the Software Angle Generator for quite some time. I made this topic previously: https://e2e.ti.com/support/microcontrollers/hercules/f/312/t/826325

In that topic I had thought I had figured it out, only to later find out I was making an error.

I still can not get the SWAG to function properly. Here is my current code:

TOOTH_PIN	.equ 2
OUT_PIN	        .equ 18

ACTUAL_TEETH .equ 58
MISSING_TEETH .equ 2
TEETH_SKIP .equ ACTUAL_TEETH - 1 
STEP_FACTOR .equ 8
GAP_START .equ ((STEP_FACTOR * (ACTUAL_TEETH - 1)) + 1)
GAP_END .equ (((STEP_FACTOR * (ACTUAL_TEETH + MISSING_TEETH )) - 1))

START   BR { cond_addr=START_00,event=NOCOND};0
START_00   APCNT { type=FALL2FALL,control=OFF,prv=OFF,period=0};1
START_0   BR { cond_addr=WAIT_FOR_LOW,event=NOCOND};2

WAIT_FOR_LOW   BR { next=START,cond_addr=WFL1,pin=2,event=HIGH};3
WFL1           MOV64 { next=START,remote=START_0,cond_addr=CALC_PERIOD,comp_mode=ECMP,reg=NONE};4

; FIFO holding last three measurements  (S01 is oldest, S03 is newest)
CALC_PERIOD   BR { next=START,cond_addr=S01,pin=2,event=FALL};5
S01   ADD  {src1=REM, src2=ZERO, dest=IMM, data=999999, hr_data=0, remote=S02}  ;N2 = S02 + 0
S02   ADD  {src1=REM, src2=ZERO, dest=IMM, data=999999, hr_data=0, remote=S03}  ;N1 = S03 + 0
S03   ADD  {src1=T,   src2=ZERO, dest=IMM, data=999999, hr_data=0}              ;N  = T + 0
S04   MOV64 { next=START,remote=START_0,cond_addr=COMPARE_PERIOD,comp_mode=ECMP,reg=NONE};

COMPARE_PERIOD   ADD { src1=REM,src2=ZERO,dest=R,remote=S01,data=0}; R = N2
S05   ADD { src1=REM,src2=R,dest=R,remote=S02,data=0}; R = N2 + R
S06   ADD { src1=R,src2=ZERO,dest=NONE,rdest=REM,remote=S07,data=0};12
S07   MCMP { en_pin_action=ON,cond_addr=BRANCH_0,pin=4,order=REG_GE_DATA,action=SET,reg=T,data=99999,hr_data=0};13
S08   MOV64 { next=START,remote=START_0,cond_addr=CALC_PERIOD,comp_mode=ECMP,reg=NONE};14
BRANCH_0   MOV64 { next=START,remote=START_0,cond_addr=SWAG_PREP1,comp_mode=ECMP,reg=NONE};15

SWAG_PREP1 BR { next=START,cond_addr=SP1,pin=TOOTH_PIN,event=HIGH};16
SP1        MOV64 { next=START,remote=START_0,cond_addr=SWAG_PREP2,comp_mode=ECMP,reg=NONE};

SWAG_PREP2 BR { next=START,cond_addr=SP20,pin=TOOTH_PIN,event=FALL};18
SP20   ADD { src1=ZERO,src2=ZERO,dest=R,data=0};
SP200      MOV64 { remote=START,cond_addr=START_0,comp_mode=ECMP,reg=NONE};
SP21        MOV64 { next=START,remote=START_0,cond_addr=WAIT_ONE_REV,comp_mode=ECMP,reg=NONE};

WAIT_ONE_REV   ECNT { pin=TOOTH_PIN,event=FALL,reg=R,data=0};22
WOR0   MCMP { next=START,cond_addr=WOR00,pin=0,order=REG_GE_DATA,reg=R,data=TEETH_SKIP};
WOR00   MOV64 { remote=START,cond_addr=START_00,comp_mode=ECMP,reg=NONE};
WOR1   MOV64 { next=START,remote=START_0,cond_addr=SWAG,comp_mode=ECMP,reg=NONE};

; Angle Counter 
SWAG   SCNT { step=STEP_FACTOR,gapstart=GAP_START,data=0}; 26
SG_01   ACNT { edge=FALLING,irq = ON, gapend=GAP_END,data=0};27
OUT20   ACMP { next=START,en_pin_action=ON,cond_addr=OUT20_PULSE_LOW,pin=OUT_PIN,action=SET,reg=B,data=0};22
; Switch OUT20
OUT20_PULSE_LOW    MOV64 { next=START,remote=OUT20,en_pin_action=ON,cond_addr=OUT20_PULSE_HIGH,pin=OUT_PIN,comp_mode=ECMP,action=CLEAR,reg=B,data=0};
OUT20_PULSE_HIGH   MOV64 { next=START,remote=OUT20,en_pin_action=ON,cond_addr=OUT20_PULSE_LOW, pin=OUT_PIN,comp_mode=ECMP,action=SET,  reg=B,data=0};

Here is the code with some description of what it's doing:

And this is what my results look like:

As you can see, the results are incorrect. 

I'm hoping someone can point me in the right direction and help me to figure out how to configure the SWAG properly. Has anyone been able to get it to work? 

  • Hello,

    The code flow looks fine to me. But the pin 18 doesn't toggle when I run your code. The pin number in ACMP bcomes zero after I click RUN. 

  • That's interesting. I'm running that exact code and I'm not seeing that issue where ACMP pin gets set to 0. You can see in the logic capture below that while ACMP is triggering at the wrong time, it is toggling the line consistently. Do you know why the ACMP pin would be set to 0? Also, do you know if the angle generator logic is running correctly on your end? 

  • Hello Mark,

    I don't have toothed wheel for the test. I created a stimulus to NHET[2] (hetm_watch_2.in in the picture below) using IDE. I don't see any output on NHET[18].

  • That's strange. I don't understand that but that OUT_PIN isn't really related to my issue. I'm mostly just using it to debug and show that the angle counter is incorrect. Since you are using the HET debug, can you see if the angle counter is correct? 

  • Hello Mark,

    I checked the value in SCNT which is correct, but I didn't check the data in ACNT. I will do another test later.

  • Sounds good! If you could, when you test it could you show me where you find the value for SCNT? I'm trying to run the debug right now and I'm having issues finding it. 

  • Hey QJ,

    So I've got my HET code running in debug. I altered it slightly to just use a 5 toothed wheel with 2 missing teeth(so 3 real teeth, 2 missing). Using this I've figured out why my angle count is not working correctly but I'm not sure how to fix it. It almost seems like a bug in the way the HET works. It's kind of a technical issue so bear with me here..

    This is the code, the only change is the ACTUAL_TEETH value:

    TOOTH_PIN   .equ 2
    OUT_PIN         .equ 18
    
    ACTUAL_TEETH .equ 3;58
    MISSING_TEETH .equ 2
    TEETH_SKIP .equ ACTUAL_TEETH - 1 
    STEP_FACTOR .equ 8
    GAP_START .equ ((STEP_FACTOR * (ACTUAL_TEETH - 1)) + 1)
    GAP_END .equ (((STEP_FACTOR * (ACTUAL_TEETH + MISSING_TEETH )) - 1))
    
    START   BR { cond_addr=START_00,event=NOCOND};
    START_00   APCNT { type=FALL2FALL,control=OFF,prv=OFF,period=0};
    START_0   BR { cond_addr=WAIT_FOR_LOW,event=NOCOND};
    
    WAIT_FOR_LOW   BR { next=START,cond_addr=WFL1,pin=2,event=HIGH};
    WFL1           MOV64 { next=START,remote=START_0,cond_addr=CALC_PERIOD,comp_mode=ECMP,reg=NONE};
    
    ; FIFO holding last three measurements  (S01 is oldest, S03 is newest)
    CALC_PERIOD   BR { next=START,cond_addr=S01,pin=2,event=FALL};
    S01   ADD  {src1=REM, src2=ZERO, dest=IMM, data=999999, hr_data=0, remote=S02}  ;N2 = S02 + 0
    S02   ADD  {src1=REM, src2=ZERO, dest=IMM, data=999999, hr_data=0, remote=S03}  ;N1 = S03 + 0
    S03   ADD  {src1=T,   src2=ZERO, dest=IMM, data=999999, hr_data=0}              ;N  = T + 0
    S04   MOV64 { next=START,remote=START_0,cond_addr=COMPARE_PERIOD,comp_mode=ECMP,reg=NONE};
    
    COMPARE_PERIOD   ADD { src1=REM,src2=ZERO,dest=R,remote=S01,data=0}; R = N2
    S05   ADD { src1=REM,src2=R,dest=R,remote=S02,data=0}; R = N2 + R
    S06   ADD { src1=R,src2=ZERO,dest=NONE,rdest=REM,remote=S07,data=0};
    S07   MCMP { en_pin_action=ON,cond_addr=BRANCH_0,pin=4,order=REG_GE_DATA,action=SET,reg=T,data=99999,hr_data=0};
    S08   MOV64 { next=START,remote=START_0,cond_addr=CALC_PERIOD,comp_mode=ECMP,reg=NONE};
    BRANCH_0   MOV64 { next=START,remote=START_0,cond_addr=SWAG_PREP1,comp_mode=ECMP,reg=NONE};
    
    SWAG_PREP1 BR { next=START,cond_addr=SP1,pin=TOOTH_PIN,event=HIGH};
    SP1        MOV64 { next=START,remote=START_0,cond_addr=SWAG_PREP2,comp_mode=ECMP,reg=NONE};
    
    SWAG_PREP2 BR { next=START,cond_addr=SP20,pin=TOOTH_PIN,event=FALL};
    SP20   ADD { src1=ZERO,src2=ZERO,dest=R,data=0};
    SP200      MOV64 { remote=START,cond_addr=START_0,comp_mode=ECMP,reg=NONE};
    SP21        MOV64 { next=START,remote=START_0,cond_addr=WAIT_ONE_REV,comp_mode=ECMP,reg=NONE};
    
    WAIT_ONE_REV   ECNT { pin=TOOTH_PIN,event=FALL,reg=R,data=0};
    WOR0   MCMP { next=START,cond_addr=WOR00,pin=0,order=REG_GE_DATA,reg=R,data=TEETH_SKIP};
    WOR00   MOV64 { remote=START,cond_addr=START_00,comp_mode=ECMP,reg=NONE};
    WOR1   MOV64 { next=START,remote=START_0,cond_addr=SWAG,comp_mode=ECMP,reg=NONE};
    
    ; Angle Counter 
    SWAG   SCNT { step=STEP_FACTOR,gapstart=GAP_START,data=0}; 
    SG_01   ACNT { edge=FALLING, gapend=GAP_END,data=0};
    OUT20   ACMP { next=START,en_pin_action=ON,cond_addr=OUT20_PULSE_LOW,pin=OUT_PIN,action=SET,reg=B,data=0};
    ; Switch OUT20
    OUT20_PULSE_LOW    MOV64 { next=START,remote=OUT20,en_pin_action=ON,cond_addr=OUT20_PULSE_HIGH,pin=OUT_PIN,comp_mode=ECMP,action=CLEAR,reg=B,data=0};
    OUT20_PULSE_HIGH   MOV64 { next=START,remote=OUT20,en_pin_action=ON,cond_addr=OUT20_PULSE_LOW, pin=OUT_PIN,comp_mode=ECMP,action=SET,  reg=B,data=0};

    I also set up a toothed gear waveform, like so:

    I'm not sure if I can export this waveform, but if I can please let me know how so that I could send it to you.

    Now when stepping through this, I've figured out why my angle was incorrect. This is right when I hit the first edge of the first tooth.

    As you can see, the ACF flag is set. This make sense because we hit the edge before we expected it.

    This is what happens on the next loop:

    When the ACNT instruction is run, it clears ACF and sets DCF. This is where the issue occurs. Because DCF is now set, for the remainder of this tooth the angle count will not be incremented. When we eventually hit an edge, DCF will be cleared and the angle count will continue to increment. This is what causes us to have a wildly inaccurate angle count. 

    Now, I'm trying to understand why DCF is set. According to the datasheet, it doesn't make any sense. ACNT only sets DCF if the counter value == GapEnd or if Data field register == GapStart, neither of those conditions are true in this case. 

    Can you shed any light on this? Am I doing something wrong here? 

  • Hello Mark,

    I run a test, I saw the DCF is set too, and the data field of ACNT is equal to GapStart.

  • Hi QJ,

    I'm using your code now, although I did make some small changes:

    1. Changed the logic to look for RISING edge

    2. Changed OUT20_PULSE_LOW to toggle on angle 0. So now we should see pin 18 toggle when angle 0 is reached. 

    TOOTH_PIN   .equ 2
    OUT_PIN         .equ 18
    
    ACTUAL_TEETH .equ 3;58
    MISSING_TEETH .equ 2
    TEETH_SKIP .equ ACTUAL_TEETH - 1 
    STEP_FACTOR .equ 8
    GAP_START .equ ((STEP_FACTOR * (ACTUAL_TEETH - 1)) + 1)
    GAP_END .equ (((STEP_FACTOR * (ACTUAL_TEETH + MISSING_TEETH )) - 1))
    
    ; Angle Counter
    L00   APCNT { next=L01,irq=OFF,type=RISE2RISE,prv=ON,period=0};
    L01   SCNT { next=L02,step=STEP_FACTOR,gapstart=GAP_START,data=0};
    L02   ACNT { next=OUT20,edge=RISING,gapend=GAP_END,data=0};
    
    ; Change OUT20
    OUT20   ACMP { next=L00,en_pin_action=ON,cond_addr=OUT20_PULSE_LOW,pin=OUT_PIN,action=SET,reg=B,data=0};
    
    ; Switch OUT20
    OUT20_PULSE_LOW   MOV64 { next=L00,remote=OUT20,en_pin_action=ON,cond_addr=OUT20_PULSE_HIGH,pin=OUT_PIN,comp_mode=ECMP,action=CLEAR,reg=B,data=0};
    OUT20_PULSE_HIGH   MOV64 { next=L00,remote=OUT20,en_pin_action=ON,cond_addr=OUT20_PULSE_LOW,pin=OUT_PIN,comp_mode=ECMP,action=SET,reg=B,data=0};
    

    And when I run that in debug, I got this signal:

    As you can see this is incorrect. When I step through it I'm seeing the same issue, where the DCF flag is set incorrectly and the angle generator missed a tooth period worth of angle counts. 

    I'm wondering if your code outputs the same? 

    I'm not really sure what to do here. I'm pretty lost. 

  • Has anyone ever gotten the SWAG to work? Is there example code somewhere? 

    Just looking through this forum I haven't seen one example of someone getting it to work. 

  • Hello Mark,

    I got the same waveform.