Shop OBEX P1 Docs P2 Docs Learn Events
Relaunching a spin cog to run pasm. variable preservation. — Parallax Forums

Relaunching a spin cog to run pasm. variable preservation.

marzec309marzec309 Posts: 146
edited 2011-07-25 20:18 in Propeller 1
If I relaunch a cog to run PASM what is the best way to preserve the variables setup in Spin? As these are being used by other cogs. My current Object is writen in spin and has proven to be to slow. If I coginit on the current cog would it trash these variables in hub ram?
«1

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2011-07-24 07:07
    Assuming we are talking about globals (VAR block), they stay untouched. Unless you explicitly change them from PASM.
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 07:31
    Yes they are global variables. I was just unsure as I've never reloaded my main program with pasm before. This is running on cog 0 and happens to be the one I used to set up the the other cogs. Thanks for clarifying that these global variables will be ok when the calling cog reinitializes it self to run some PASM.
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-24 07:35
    marzec309 wrote: »
    This is running on cog 0 and happens to be the one I used to set up the the other cogs.
    Don't tie yourself to a specific cog though. Use coginit(cogid, @entry, parameter) instead.
  • StefanL38StefanL38 Posts: 2,292
    edited 2011-07-24 07:59
    What is the advantage of using coginit to start PASM-code over using cognew for starting PASM-cogs?

    From my actual knowledge (wich can be improved quite a lot) I always use cognew to be sure the prop-chip itslefs manages completely which cog to use for what

    best regards

    Stefan
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-07-24 08:06
    In Kuroneko's example, the PASM cog replaces the Spin cog that launches it. If there were seven other cogs running, cognew would fail. Normally, though, coginit should never be used. This is one of those rare exceptions.

    -Phil
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 08:26
    kuroneko wrote: »
    Don't tie yourself to a specific cog though. Use coginit(cogid, @entry, parameter) instead.

    Ya that's how I would have done it. I just mentioned cog 0 because that's is the cog its running on, as its the one the propeller booted on start up(the top most object) and thus were my uncertanty started.

    @Phil That would be exactly my situation. At the time this instrucion would exicute all eight cogs are running. The only cog availabe for reperpousing would be the calling cog.

    Sorry for any typos or grammer mistakes I'm using my phone don't have access to my laptop at the moment.
  • Cluso99Cluso99 Posts: 18,069
    edited 2011-07-24 14:28
    How much and how fast pasm do you have to run? There is a modified spin interpreter that permits calling LMM pasm routines (its ~4x slower than real pasm).
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 16:50
    Cluso99 wrote: »
    How much and how fast pasm do you have to run? There is a modified spin interpreter that permits calling LMM pasm routines (its ~4x slower than real pasm).
    I haven't performed any speed testing yet but i just found out yesterday that my down and dirty Spin code was to slow to respond to a couple proximity sensors monitoring a spinning(no pun intended) shaft. Its still busy updating some global variables after the first prox was triggered and misses the second proximity signal. Here is that chunk of code:
    pri  Sort | BlowOffDisable, errorSkip
    
      BlowOffDisable := 0
      ErrorSkip := 0
    
      FRQA := $00000001
      CTRA := %11111 << 26 
      
      repeat
    
        repeat until dataIn & CutSigMsk == CutSigMsk
    
        PHSA := $00000000
    
        if RLYOutput & CutDisableMsk == CutDisableMsk
          RLYOutput |= CounterDisableMsk
          BlowOffDisable := 2
          if status <> 2
            Status := 1
          ErrorSkip := 1
        Else
          repeat
        
            if RLYOutput & Alarm2Msk == Alarm2Msk
              RLYOutput |= Alarm1Msk + CounterDisableMsk 
              BlowOffDisable := 3
              status := 2
              ErrorSkip := 1
              
          Until dataIn & CutPosProxMsk == CutPosProxMsk
                                                             
        if errorSkip == 0
          CycleTime[0] := PHSA 
          logLength := LengthBuffer
          lengthBuffer := 0
    
          repeat until DataIn & KnifeProxMsk == KnifeProxMsk
          
          CycleTime[1] := PHSA
          
        else
          ErrorSkip--
        
        if BlowOffDisable == 0
          RLYOutput |= BlowOffMsk
          waitcnt((clkfreq / 1000) * 100 + cnt)
          RLYOutput ^= BlowOffMsk
        else
          BlowOffDisable--
    
        if (RLYOutput & CounterDisableMsk == CounterDisableMsk) and BlowOffDisable == 0
          RLYOutput ^= CounterDisableMsk
    
    
    This shouldn't be to difficult to port to pasm. but what is this LMM you are refering too?
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 17:45
    Now how about constants can these be accessed from PASM also? I'm probably going to have to set these up as variables huh?
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-24 17:54
    Everything defined in CON sections is directly visible (note the 9bit limit for literals though). Do you have a specific example?
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 18:03
    kuroneko wrote: »
    Everything defined in CON sections is directly visible (note the 9bit limit for literals though). Do you have a specific example?

    Ya here is the code:
    con
    
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    ' _xinfreq = 6_250_000
    
    
    
    'Control Constants  
      UltraUBufferSize = 20
      maxSD            = 14
      alarmTime        = (80_000_000 / 1000) * 42
    
    'Output Asignments
      CutDisableMsk      = %1000_0000
      BlowOffMsk         = %0010_0000
      CounterDisableMsk  = %0100_0000
      Alarm1Msk          = %0000_0010
      Alarm2Msk          = %0000_0001
    
    'Input Asignments
      EnableMsk        = %1000_0000
      CutSigMsk        = %0100_0000
      KnifeProxMsk     = %0010_0000
      CutPosProxMsk    = %0001_0000
      ResetMsk         = %0000_0001
      EncAMsk          = %0000_1000
      EncBMsk          = %0000_0100
      EncCMsk          = %0000_0001
      
    
    var
    
      Long  LengthBuffer
      Long  LogLength       
      Long  ErrorBuffer
      Long  StandardDeviation
      Long  CycleTime[2]
      word  BufferPool[UltraUBufferSize]
      byte  BufferCnt
      Byte  UltraUBufferLock
      Byte  I2CLock
      Byte  CogCnt
      Byte  Status
      Byte  RLYOutput
      Byte  DataIn
         
      
      
    obj
      lcd     :       "lcd4Bit"
      Sonic   :       "UltraU_Stream"
      BLOBJ   :       "Buff_Loader_OBJ2"
      DigO    :       "IO_Board_Output_Driver"
      DigI    :       "IO_Board_Input_Driver_PASM"
      Encoder :       "Encoder_Driver"
    
    dat
    Version        byte    "5.03", 0
    Str0           byte    "                ", 0
    Str1           byte    "        P-CAM   ", 0
    Str2           byte    "  Modual        ", 0
    Str3           byte    "Booting ", 0
    Str4           byte    "Lcd Drv ", 0
    Str5           byte    "SonicDrv", 0
    Str6           byte    " In Drv ", 0
    str7           byte    "Out Drv ", 0
    str8           byte    "Enc Drv ", 0
    str9           Byte    "RUNNING ", 0
    str10          byte    " STOPPED", 0
    str11          byte    "        ", 0
    str12          byte    "UNSTABLE", 0
    str13          byte    "SD calc ", 0
    Pass           Byte    "Success.", 0
    Fail           Byte    "  Fail  ", 0
      
    Pub main      | tmp
    
    'bootup
    
      UltraUBufferLock := LockNew
    
      IF lcd.init(8,8,2)
        lcd.blon
        lcd.scrollstr(1, 1, 8, 100, @str1)                           
        lcd.rscrollstr(1, 2, 8, 100, @str2)
        waitcnt(cnt + clkfreq / 2)
        lcd.moveto(1,2)
        lcd.str(string("Ver#"))
        lcd.str(@Version)
        waitcnt(cnt+clkfreq/2)
        lcd.moveto(1,1)
        lcd.str(@str3)
        lcd.moveto(1,2)
        lcd.str(@Str5)
        waitcnt(cnt + (clkfreq / 1000 * 500))                               
        IF Sonic.Start(31,30,@BufferPool,@BufferCnt,@LengthBuffer,@LogLength,@ErrorBuffer,@CycleTime,UltraUBufferSize,UltraUBufferLock,EnableMsk,KnifeProxMsk,CutPosProxMsk,@Status,@DataIn)
          lcd.moveto(1,2)
          lcd.str(@Str6)
          waitcnt(cnt + (clkfreq / 1000 * 500))
          if DigI.Start(@DataIn)
            lcd.moveto(1,2)
            lcd.str(@str7)
            waitcnt(cnt + (clkfreq / 1000 * 500))
            if DigO.Start(@RLYOutput)
              lcd.moveto(1,2)
              lcd.str(@str8)
              waitcnt(cnt + (clkfreq / 1000 * 500))
              if Encoder.Start(EncAMsk,EncBMsk,EncCMsk,@LengthBuffer,@ErrorBuffer,@DataIn)
                lcd.moveto(1,2)
                lcd.str(@str13)
                waitcnt(cnt + (clkfreq / 1000 * 500))
                if (tmp := BLOBJ.Start(@DataIn, @BufferPool,@ErrorBuffer,@RLYOutput,@Status,EnableMsk,ResetMsk,CutDisableMsk,Alarm1Msk,Alarm2Msk,MaxSD,UltraUBufferSize)) 
                  lcd.moveto(1,2)
                  lcd.str(@Pass)
                  lcd.finalize
                  Sort
                else
                  lcd.moveto(1,1)
                  lcd.str(@fail)
                  reboot  
              else
                lcd.moveto(1,1)
                lcd.str(@fail)
                reboot
            else
              lcd.moveto(1,1)
              lcd.str(@Fail)
              reboot
          else
            lcd.moveto(1,1)
            lcd.str(@Fail)
            reboot
        else
          lcd.moveto(1,1)
          lcd.str(@Fail)
          Reboot         
      else
        Reboot          
        
    pri  Sort | BlowOffDisable, errorSkip
    
      BlowOffDisable := 0
      ErrorSkip := 0
    
      FRQA := $00000001
      CTRA := %11111 << 26 
      
      repeat
    
        repeat until dataIn & CutSigMsk == CutSigMsk
    
        PHSA := $00000000
    
        if RLYOutput & CutDisableMsk == CutDisableMsk
          RLYOutput |= CounterDisableMsk
          BlowOffDisable := 2
          if status <> 2
            Status := 1
          ErrorSkip := 1
        Else
          repeat
        
            if RLYOutput & Alarm2Msk == Alarm2Msk
              RLYOutput |= Alarm1Msk + CounterDisableMsk 
              BlowOffDisable := 3
              status := 2
              ErrorSkip := 1
              
          Until dataIn & CutPosProxMsk == CutPosProxMsk
                                                             
        if errorSkip == 0
          CycleTime[0] := PHSA 
          logLength := LengthBuffer
          lengthBuffer := 0
    
          repeat until DataIn & KnifeProxMsk == KnifeProxMsk
          
          CycleTime[1] := PHSA
          
        else
          ErrorSkip--
        
        if BlowOffDisable == 0
          RLYOutput |= BlowOffMsk
          waitcnt((clkfreq / 1000) * 100 + cnt)
          RLYOutput ^= BlowOffMsk
        else
          BlowOffDisable--
    
        if (RLYOutput & CounterDisableMsk == CounterDisableMsk) and BlowOffDisable == 0
          RLYOutput ^= CounterDisableMsk
    
          
    
    I'm porting the PRI Sort to PASM to be relaunched into the same cog. I know how the get the address of the global variables into PASM, Can I Pass the address of the constants to the PASM routine or even use those constants in PASM and have the compiler do it for me?

    This is how I'm trying to get the variables into PASM:
    Dat
    
                            org     0
    sort                    mov     tmp, par
                            mov     LengthBufferAddr, tmp
                            add     tmp, #4
                            mov     LogLengthAddr,tmp
                            add     tmp, #12
                            mov     Cycle1TimeAddr, tmp
                            add     tmp, #4
                            mov     Cycle2TimeAddr, tmp
                            add     tmp, #7
                            mov     StatusAddr, tmp
    
    
    
    LengthBufferAddr        res       1
    LengthHolderAddr        res       1
    Cycle1TimeAddr          res       1
    Cycle2TimeAddr          res       1
    StatusAddr              res       1
    tmp                     res       1
    

    Was not sure how to get the predefined constants into PASM.
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-24 18:12
    Except for alarmTime just use them, e.g.
    or  dira, #ResetMsk
    
    alarmTime is bigger (doesn't fit into 9bit) so you'd have to sacrifice a register like this
    mov     time, aTime
    
    aTime   long    alarmTime
    
    For stuff like counter initialisation use
    mov[COLOR="red"]i[/COLOR]    ctra, #%0_11111_000          ' LOGIC always
    
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 18:20
    What exactly do you mean by "9bit"? If I follow you right Constants can't be longer than 9 bits in PASM!?
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-24 18:26
    Literal constants are limited, i.e. ones which are embedded into the instruction itself. This is because the dst and src fields are only 9bit (512 registers). So if you need bigger stuff (which can't be done through mov[dis] or neg & Co) you'll have to squirrel it away into a spare register and access it by reference. In the first example I used # which indicates an embedded literal. In the second example I (mis)use a register and address that (no #). There is no timing penalty, just space.

    The only issue I see with the sort method is the waitcnt target which may have to go into a constant pool in your cog image.
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 20:38
    kuroneko wrote: »
    Except for alarmTime just use them, e.g.
    or  dira, #ResetMsk
    
    alarmTime is bigger (doesn't fit into 9bit) so you'd have to sacrifice a register like this
    mov     time, aTime
    
    aTime   long    alarmTime
    
    For stuff like counter initialisation use
    mov[COLOR=red]i[/COLOR]    ctra, #%0_11111_000          ' LOGIC always
    


    OK, I tried to use the variables as they are, it will not compile. Could you tell me what I've done wrong? can i use "test" with two variables?
    Dat
    
                            org     0
    sort                   mov     BlowOffDisable, #0
                            mov     ErrorSkip, #0
                            mov     frqa, #1
                            movi    ctra, #%0_11111_000          ' LOGIC always
    
    
    :loop
    
    :waitCutSig        test    DataIn, #CutSigMsk       wz
                  if_z      jmp     #:waitCutSig
    
                            mov     phsa,#0
                            test    RLYOutput, #CutdisableMsk wz
                  if_z      jmp     #:testAlarm
                            or      RLYOutput, #CounterDisableMsk
                            mov     BlowOffDisable, #2
                            cmp     Status, #2              wz
                  if_ne     mov     status, #1
                            mov     ErrorSkip, #1
    
    :testAlarm              test    RLYOutput, #Alarm2Msk    wz
                  if_nz     jmp     #:CheckCutPos
                            or      RLYOutput, #Alarm1Msk
                            or      RLYOutput, #CounterDisableMsk
                            mov     BlowOffDisable,#3
                            mov     status, #2
                            mov     errorSkip, #1
                            
    :CheckCutPos            test    dataIn, #CutPosProxMsk   wz
                  if_z      jmp     #testAlarm                                                 
    
    :CheckSkip              cmp     errorSkip, #0
                  if_ne     jmp     #:DecrementErrorSkip
                            mov     CycleTime[0], phsa
                            mov     LogLength, LengthBuffer
                            mov     lengthBuffer, #0
    
    :CheckStopProx          test    DataIn, #KnifeProxMsk    wz
                  if_z      jmp     #:CheckStopProx
                            mov     CycleTime[1], phsa                       
    
    :DecrementErrorSkip     sub     errorSkip, #1
    
                            cmp     BlowOffDisable, #0      wz
                  if_ne     jmp     #:DecrementBlowOffDis
                            or      RLYOutput, #BlowOffMsk
                            mov     tmp, outtime
                            add     tmp, cnt
                            waitcnt tmp, #0
                            xor     RLYOutput, #BlowOffMsk
                            
    :DecrementBlowOffDis    sub     BlowOffDisable, #1
    
                            test    RLYoutput, #CounterdisableMsk   wz
                  if_nz     cmp     BlowoffDisable, #0              wz
                  if_e      xor     RLYOutput, CounterDisableMsk
    
                            jmp     #:loop
    
    outtime long  outputTime
    
    tmp            res 1
    BlowOffDisable res 1
    ErrorSkip      res 1
    
  • Cluso99Cluso99 Posts: 18,069
    edited 2011-07-24 20:43
    LMM uses hub to store a copy of each pasm instruction to be executed. It is copied into the cog to be executed, one instruction at a time.

    I am presuming you do not have a spare cog??? If you do, then what you are trying to do would be relatively easy in another cog running pasm, without the need to relaunch it.
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-24 20:45
    The mov CycleTime[n], phsa notation is invalid. Also note that SPIN variables live in hub RAM. All the PASM cog knows are their addresses. So you'll need to access the hub (rdlong), do some operation on them and (optionally) write them back (wrlong).
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 20:54
    Cluso99 wrote: »
    LMM uses hub to store a copy of each pasm instruction to be executed. It is copied into the cog to be executed, one instruction at a time.

    I am presuming you do not have a spare cog??? If you do, then what you are trying to do would be relatively easy in another cog running pasm, without the need to relaunch it.

    No, I don't have a spare cog and thus why I'm having difficulties. the use of LMM is very interesting.
    kuroneko wrote: »
    The mov CycleTime[n], phsa notation is invalid. Also note that SPIN variables live in hub RAM. All the PASM cog knows are their addresses. So you'll need to access the hub (rdlong), do some operation on them and (optionally) write them back (wrlong).

    Thanks I'll try reading them into a temp variable first. I didn't think mov CycleTime[n], phsa was valid ether, I just figured i would cross that bridge when I got to it. :) Sloppy I know :/
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 21:14
    Though I'm still under the impression I have to send the address of my first variable with coginit then set up all my variable addresses off of the first one. It doesn't appear that the pasm even knows the address, as i still get the compile error "Expected a constant, unary operator, or "("." when using a global variable set up in a VAR block.
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-24 21:14
    This may help with the address setup. If you have more you might consider a loop.
    VAR
      [COLOR="red"]long  eins[/COLOR]
      long  zwei
      long  drei[3]
      long  vier
    
    PUB null
    
      coginit(cogid, @entry, @eins)                                 
      
    DAT             org     0
    
    entry           add     eins_, par              ' resolve addresses from offsets
                    add     zwei_, par              '
                    add     drei_, par              '
                    add     vier_, par              '
    
                    rdlong  temp, eins_             ' access to [color=red]long eins[/color]
    
    '               ...
                    
    eins_           long    0                       ' holds VAR hub addresses
    zwei_           long    4                       ' these values are preset with their
    drei_           long    8  {3 longs}            ' corresponding offsets
    vier_           long    20                      '
    
                    fit
    
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-24 21:16
    marzec309 wrote: »
    Though I'm still under the impression I have to send the address of my first variable with coginit then set up all my variable addresses off of the first one.
    As I said, only CON is directly usable (compile time). VAR access is by reference (i.e. passing the base address and resolve offsets).
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 21:18
    AH, makes a lot more sense. I could have swore you said use them as they are, my mistake. I do appreciate your fast replies.
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-24 21:21
    marzec309 wrote: »
    I could have swore you said use them as they are, my mistake.
    Apologies, the context wasn't too clear (after re-reading). I was only referring to constants.
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 21:28
    kuroneko wrote: »
    Apologies, the context wasn't too clear (after re-reading). I was only referring to constants.

    That is OK, What I wrote isn't useless, I just have to set up my variables and append my code a little. I should be able to make it work. Even having to read the variables from the hub ram, it should be a lot faster than its SPIN equivalent.
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 22:18
    OK, I've finished appending my code and it compiles. YAY I'll test it out tomorrow morning once I get to work. But in the mean time I need to get some sleep. Here my code untested as of now but Compiling at the least.
    con
    
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    ' _xinfreq = 6_250_000
    
    
    
    'Control Constants  
      UltraUBufferSize = 20
      maxSD            = 14
      OutputTime       = (80_000_000 / 1000) * 100
    
    'Output Asignments
      CutDisableMsk      = %1000_0000
      BlowOffMsk         = %0010_0000
      CounterDisableMsk  = %0100_0000
      Alarm1Msk          = %0000_0010
      Alarm2Msk          = %0000_0001
    
    'Input Asignments
      EnableMsk        = %1000_0000
      CutSigMsk        = %0100_0000
      KnifeProxMsk     = %0010_0000
      CutPosProxMsk    = %0001_0000
      ResetMsk         = %0000_0001
      EncAMsk          = %0000_1000
      EncBMsk          = %0000_0100
      EncCMsk          = %0000_0001
      
    
    var
    
      Long  LengthBuffer
      Long  LogLength       
      Long  ErrorBuffer
      Long  StandardDeviation
      Long  CycleTime[2]
      word  BufferPool[UltraUBufferSize]
      byte  BufferCnt
      Byte  UltraUBufferLock
      Byte  I2CLock
      Byte  CogCnt
      Byte  Status
      Byte  RLYOutput
      Byte  DataIn
         
      
      
    obj
      lcd     :       "lcd4Bit"
      Sonic   :       "UltraU_Stream"
      BLOBJ   :       "Buff_Loader_OBJ2"
      DigO    :       "IO_Board_Output_Driver"
      DigI    :       "IO_Board_Input_Driver_PASM"
      Encoder :       "Encoder_Driver"
    
    dat
    Version        byte    "6.00", 0
    Str0           byte    "                ", 0
    Str1           byte    "        P-CAM   ", 0
    Str2           byte    "  Modual        ", 0
    Str3           byte    "Booting ", 0
    Str4           byte    "Lcd Drv ", 0
    Str5           byte    "SonicDrv", 0
    Str6           byte    " In Drv ", 0
    str7           byte    "Out Drv ", 0
    str8           byte    "Enc Drv ", 0
    str9           Byte    "RUNNING ", 0
    str10          byte    " STOPPED", 0
    str11          byte    "        ", 0
    str12          byte    "UNSTABLE", 0
    str13          byte    "SD calc ", 0
    Pass           Byte    "Success.", 0
    Fail           Byte    "  Fail  ", 0
      
    Pub main      
    
    'bootup
    
      UltraUBufferLock := LockNew
    
      IF lcd.init(8,8,2)
        lcd.blon
        lcd.scrollstr(1, 1, 8, 100, @str1)                           
        lcd.rscrollstr(1, 2, 8, 100, @str2)
        waitcnt(cnt + clkfreq / 2)
        lcd.moveto(1,2)
        lcd.str(string("Ver#"))
        lcd.str(@Version)
        waitcnt(cnt+clkfreq/2)
        lcd.moveto(1,1)
        lcd.str(@str3)
        lcd.moveto(1,2)
        lcd.str(@Str5)
        waitcnt(cnt + (clkfreq / 1000 * 500))                               
        IF Sonic.Start(31,30,@BufferPool,@BufferCnt,@LengthBuffer,@LogLength,@ErrorBuffer,@CycleTime,UltraUBufferSize,UltraUBufferLock,EnableMsk,KnifeProxMsk,CutPosProxMsk,@Status,@DataIn)
          lcd.moveto(1,2)
          lcd.str(@Str6)
          waitcnt(cnt + (clkfreq / 1000 * 500))
          if DigI.Start(@DataIn)
            lcd.moveto(1,2)
            lcd.str(@str7)
            waitcnt(cnt + (clkfreq / 1000 * 500))
            if DigO.Start(@RLYOutput)
              lcd.moveto(1,2)
              lcd.str(@str8)
              waitcnt(cnt + (clkfreq / 1000 * 500))
              if Encoder.Start(EncAMsk,EncBMsk,EncCMsk,@LengthBuffer,@ErrorBuffer,@DataIn)
                lcd.moveto(1,2)
                lcd.str(@str13)
                waitcnt(cnt + (clkfreq / 1000 * 500))
                if BLOBJ.Start(@DataIn, @BufferPool,@ErrorBuffer,@RLYOutput,@Status,EnableMsk,ResetMsk,CutDisableMsk,Alarm1Msk,Alarm2Msk,MaxSD,UltraUBufferSize) 
                  lcd.moveto(1,2)
                  lcd.str(@Pass)
                  lcd.finalize
                  'sort
                  Coginit(CogID,@sort,@lengthBuffer)
                else
                  lcd.moveto(1,1)
                  lcd.str(@fail)
                  reboot  
              else
                lcd.moveto(1,1)
                lcd.str(@fail)
                reboot
            else
              lcd.moveto(1,1)
              lcd.str(@Fail)
              reboot
          else
            lcd.moveto(1,1)
            lcd.str(@Fail)
            reboot
        else
          lcd.moveto(1,1)
          lcd.str(@Fail)
          Reboot         
      else
        Reboot          
    
    
    Dat
    
                            org     0
    sort                    add     LengthBuffer_, par
                            add     LogLength_, par
                            add     CycleTime_, par
                            add     Status_, par
                            add     RLYOutput_, par
                            add     DataIn_, par
    
    
    
                            mov     BlowOffDisable, #0
                            mov     ErrorSkip, #0
                            mov     frqa, #1
                            movi    ctra, #%0_11111_000          ' LOGIC always
    
    
    :loop
    
    :waitCutSig             rdbyte  tmp, DataIn_
                            test    tmp, #CutSigMsk       wz
                  if_z      jmp     #:waitCutSig
    
                            mov     phsa,#0
                            rdbyte  tmp, RLYOutput_
                            test    tmp, #CutdisableMsk wz
                  if_z      jmp     #:testAlarm
                            rdbyte  tmp, RLYOutput_
                            or      tmp, #CounterDisableMsk
                            wrbyte  tmp, RLYOutput_
                            mov     BlowOffDisable, #2
                            rdbyte  tmp, status_
                            cmp     tmp, #2              wz
                  if_ne     wrbyte  1, status_
                            mov     ErrorSkip, #1
    
    :testAlarm              rdbyte  tmp, RLYOutput_
                            test    tmp, #Alarm2Msk    wz
                  if_nz     jmp     #:CheckCutPos
                            rdbyte  tmp, RLYOutput_
                            or      tmp, #Alarm1Msk
                            or      tmp, #CounterDisableMsk
                            wrbyte  tmp, RLYOutput_
                            wrbyte  2, status_
                            mov     BlowOffDisable,#3
                            mov     errorSkip, #1
                            
    :CheckCutPos            rdbyte  tmp, datain_
                            test    tmp, #CutPosProxMsk   wz
                  if_z      jmp     #:testAlarm                                                 
    
    :CheckSkip              cmp     errorSkip, #0
                  if_ne     jmp     #:DecrementErrorSkip
                            wrlong  phsa, cycletime_
                            rdlong  tmp, LengthBuffer_
                            wrlong  tmp, LogLength_
                            wrlong  0, LengthBuffer_
    
    :CheckStopProx          rdbyte  tmp, DataIn_
                            test    tmp, #KnifeProxMsk    wz
                  if_z      jmp     #:CheckStopProx
                            mov     tmp, cycleTime_
                            add     tmp, #4
                            wrlong  phsa, tmp                       
                            jmp     #:BlowOff
                            
    :DecrementErrorSkip     sub     errorSkip, #1
    
    :BlowOff                cmp     BlowOffDisable, #0      wz
                  if_ne     jmp     #:DecrementBlowOffDis
                            rdbyte  tmp, RLYOutput_
                            or      tmp, #BlowOffMsk
                            wrbyte  tmp, RLYOutput_
                            mov     tmp, outtime
                            add     tmp, cnt
                            waitcnt tmp, #0
                            rdbyte  tmp, RLYOutput_
                            xor     tmp, #BlowOffMsk
                            wrbyte  tmp, RLYOutput_
                            
    :DecrementBlowOffDis    sub     BlowOffDisable, #1
    
                            rdbyte  tmp, RLYOutput_
                            test    tmp, #CounterdisableMsk   wz
                  if_nz     cmp     BlowoffDisable, #0              wz
                  if_e      xor     tmp, CounterDisableMsk
                  if_e      wrbyte  tmp, RLYOutput_
                            jmp     #:loop
    
    
    
    '*****************************************************************
    
    
    LengthBuffer_ long      0
    LogLength_    long      4
    CycleTime_    long      16
    Status_       long      27
    RLYOutput_    long      28
    DataIn_       long      29      
    
    outtime       long  outputTime
    
    tmp            res 1
    BlowOffDisable res 1
    ErrorSkip      res 1
                          
    
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-24 22:31
                  if_ne     wrbyte  1, status_
                            wrbyte  2, status_
                            wrlong  phsa, cycletime_
                            wrlong  0, LengthBuffer_
                            wrlong  phsa, tmp                       
    
    Putting 0..2 into the destination slot doesn't do what you think it does. It's effectively addressing registers 0..2. Also, phsa - if used in the destination slot - only writes the shadow register, not the counter. So at least do:
    mov     temp, phsa
    wrlong  temp, addr
    
    As for writing zero use wrlong par, LengthBuffer_ (par's shadow is usually empty), 1 and 2 should use register references or you could hi-jack some of the code, e.g.
    _one                    mov     frqa, #1
                            ...
                  if_ne     wrbyte  _one, status_
    
    and
    _two                    cmp     tmp, #2              wz
                            ...
                            wrbyte  _two, status_
    
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 22:51
    Call me tired but I'm not following you.
    wrbyte  1, status_
    
    was trying to write a decimal 1 to address @status along with dec 2 later on.

    I understand what you said about:
    mov     temp, phsa 
    wrlong  temp, addr
    
    But i don't understand this at all
    _one                    mov     frqa, #1              
             if_ne     wrbyte  _one, status_ 
    
    
    _two                    cmp     tmp, #2              wz
                           wrbyte  _two, status_ 
    
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 22:58
    On the last part couldn't I just set up a couple of constants first and then use though to write these values to the hub address, or move them into a temp variable first?
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-24 23:00
    I know that this was most likely the intention. Problem is that literals (#L) are only usable in the src slot of the instruction. mov phsa, 0 is not necessarily the same as mov phsa, #0. The former copies register 0 to phsa which is whatever your first instruction is (e.g. add LengthBuffer_, par) the latter really copies binary zero into phsa.

    That said, you can't do wrlong #1, addr. It has to be along the lines of
    wrbyte  _one, addr
            ...
    _one    long    1
    _two    long    2
    
    So instead of defining two new register constants (for 1 and 2) the code below uses existing instructions where it knows that the lower byte (source for wrbyte) has the appropriate value.
    _one               mov     frqa, [COLOR="red"]#1[/COLOR]              
                       ...
             if_ne     wrbyte  _one, status_ 
    
    
    _two               cmp     tmp, [COLOR="red"]#2[/COLOR] wz
                       ...
                       wrbyte  _two, status_ 
    
    I probably get -10 points for doing (or even suggesting) it but I think it's useful.
  • marzec309marzec309 Posts: 146
    edited 2011-07-24 23:08
    just had an ahah moment. that is very clever. The _one and _two are addresses like in a jmp but when used like wrbyte _two, status_ its writing the source of the instruction at address _two. right?
Sign In or Register to comment.