Shop OBEX P1 Docs P2 Docs Learn Events
if/else Assembly input/output pins — Parallax Forums

if/else Assembly input/output pins

Hello,

I am having an issue with the assembly code attached,
I have two input pins - Pin 24 and pin 26, if low I call an assembly function to build a signal, if High I call a different signal

I use xor and if_z or If_nz to determine the jump, the problem is it only works sometimes, so odds are it is incorrect,

what is weird is that if I swap the if_z to if_nz and vice versa, I get it to work correctly for awhile, then it reverses. so i think the tests are wrong or giving me the wrong flag.

I have attached the code. I would like a different test method, basically a If/else test of a input pin and output to an output pin, for two different input pins and two different output pins.

thanks in advance.

regards

Jeff
CON
  _CLKMODE = xtal1 + pll16x
  
  _XINFREQ = 6_200_000

  MY_PIN_24 = 24

PUB main

  cognew(@lfs_heater, 0) ' Start a Cog with our assembly routine, no stack
                    ' is required since PASM requires we explicitly
                    ' assign and use memory locations within the Cog/Hub
DAT
        org     0
LFS_heater      mov     dira, Both_P2_P5_output'   Pin24       ' Set our Pin to an output
                mov     outa,Both_P2_P5_low 
             'mov     dira,   Pin26
                rdlong  Delay,  #0
               
                
:keep_checking  mov     temp1, ina              'Get the current inputs
                and     temp1, Input_P24_P26_Mask  'Mask the inputs that you care about
      ' check ping 24          
                
                xor  temp1, Just_input_pin24 wz,nr 'Check if just input 24 is high

       if_z     jmpret :On_Signal_Base_ret,#:On_Signal_Base_int
       
                 
                 
                 xor  temp1, Just_input_pin24 wz,nr 'Check if just input 24 is low
       '
       if_nz    jmpret:Off_Signal_Base_ret,#:Off_Signal_Base_int

                 

       '  check ping 26
            
                xor  temp1, Just_input_pin26 wz,nr 'Check if just input 26 is high
     
       if_z      jmpret :On_Signal_Hopper_ret,#:On_Signal_Hopper_int

                 

                xor  temp1, Just_input_pin26 wz,nr 'Check if just input 2 is low
                
       if_nz    jmpret :Off_Signal_Hopper_ret,#:Off_Signal_Hopper_int

                
       
                jmp#:keep_checking

:Off_Signal_Base_int    
                        mov     Time,   cnt       ' Prime our timer with the current value of the system counter
                        add     Time,   Period200us       ' Add a minimum delay ( more on this below )
:Off_Signal_Base        waitcnt Time, #14     ' Start waiting       
                        xor outa, Pin2
                        waitcnt       Time,#12
                        xor outa, Pin2
                        waitcnt       Time,#24
                        xor outa, Pin2
                        waitcnt       Time,#24
                        xor outa, Pin2
                        waitcnt       Time,#49
                        xor outa, Pin2
                        waitcnt       Time, #49
                        xor outa, Pin2
                        waitcnt       Time, #24
                        xor outa, Pin2
                        waitcnt       Time, #24
                        xor outa, Pin2
:Off_Signal_Base_ret   jmp# 0


:Off_Signal_Hopper_int
                        
                        mov     Time,   cnt       ' Prime our timer with the current value of the system counter
                        add     Time,   Period200us       ' Add a minimum delay ( more on this below )
:Off_Signal_Hopper      waitcnt Time, #14     ' Start waiting       
                        xor outa, Pin5
                        waitcnt       Time,#12
                        xor outa, Pin5
                        waitcnt       Time,#24
                        xor outa, Pin5
                        waitcnt       Time,#24
                        xor outa, Pin5
                        waitcnt       Time,#49
                        xor outa, Pin5
                        waitcnt       Time, #49
                        xor outa, Pin5
                        waitcnt       Time, #24
                        xor outa, Pin5
                         waitcnt       Time, #24
                        xor outa, Pin5
:Off_Signal_Hopper_ret   jmp# 0

:On_Signal_Base_int
                        mov     Time,   cnt       ' Prime our timer with the current value of the system counter
                        add     Time,  Period200us     ' Add a minimum delay ( more on this below )        
:On_Signal_Base         waitcnt Time,   #10       ' Start waiting
                        xor outa, Pin2   
                        waitcnt       Time,#40      
                        xor outa, Pin2 
                        waitcnt       Time,#75
                        xor outa, Pin2 
                        waitcnt       Time,#50  
                        xor outa, Pin2  
                        waitcnt       Time,#25 
                        xor outa, Pin2  
                        waitcnt       Time,#25
                        xor outa, Pin2
:On_Signal_Base_ret     jmp# 0

:On_Signal_Hopper_int   mov     Time,   cnt       ' Prime our timer with the current value of the system counter
                        add     Time,   Period200us        ' Add a minimum delay ( more on this below )        
 :On_Signal_Hopper      waitcnt Time,  #10      ' Start waiting
                        xor outa, Pin5   
                        waitcnt       Time,#40     
                        xor outa, Pin5 
                        waitcnt       Time,#75 
                        xor outa, Pin5 
                        waitcnt       Time,#50   
                        xor outa, Pin5  
                        waitcnt       Time,#25 
                        xor outa, Pin5  
                        waitcnt       Time,#25
                        xor outa, Pin5
:On_Signal_Hopper_ret   jmp# 0                        
                      

Pin2    long    |< 2     ' Encde PIN to a bit mask
Pin5    long    |< 5     ' Encde PIN to a bit mask    
Input_5 long    |< 5
Period200us     long  20000 '  100  us
temp            long
Input_3_5_Mask  long      %00000000_0010_1000
Input_2_5_Mask  long      %00000000_0010_0100
Just_input_pin5  long     %00000000_0010_0000
Just_input_pin2  long     %00000000_0000_0100
Just_input_pin24   long     %00000001_00000000_00000000_00000000
Just_input_pin24_L long     %11111110_11111111_11111111_11111111  
Just_input_pin26   long     %00000100_00000000_00000000_00000000
Just_input_pin26_L long     %11111011_11111111_11111111_11111111      
Just_input_pin3  long     %00000000_0000_1000          
Input_P24_P26_Mask   long     %00000101_00000000_00000000_00000000
Input_P24_P26_Mask_L long     %11111010_11111111_11111111_11111111 
Both_P2_P5_output   long      %00000000_00000000_00000000_00100100
Both_P2_P5_low     long      %00000000_00000000_00000000_00000000                                    
temp1 long 0          
Delay           res     1
Time            res     1
FIT 496

Comments

  • Personally I would use the test instruction to check the state of a pin, rather than xor ,nr, as that seems more intuitive (and then the jump conditions don't have to be reversed -- xor flips the bit, test does not). I would also use "ret" rather than "jmp #0" to return from subroutine, although that's just a style issue. The basic logic seems sound, at least at first glance, although your device has a funny way of being controlled (the Off_Signal_Base and On_Signal_Base functions are awfully similar, just differing in timings).

    If you ever want help in some PASM logic, one quick and dirty way to check it might be to write the code in Spin and then translate it to PASM using the Spin Converter program. Spin Converter is still very alpha, but simple if/then/else control logic and pin manipulation should work fine.
  • altosackaltosack Posts: 132
    edited 2016-03-03 18:07
    While you can use JMPRET mostly in the way you've done it, there are some conventions used in the assembler that make it easier and more like other processor assembly language. In your instance, you can make it work by adding a '#' to the destination (first) operand, also: "jmpret #:Off_Signal_Base_ret, #:Off_Signal_Base_int" instead of "jmpret :Off_Signal_Base_ret, #:Off_Signal_Base_int".

    There are specific instances where you want to use the JMPRET instruction (i.e., coroutines), but for normal subroutine call/ret, you should use those assembler mnemonics, as follows:
    Main_code:      call    #Subroutine
    
    ...
    
    Subroutine:     xor     pin, #1
    ...
    Subroutine_ret: ret
    
    Note that there is no PASM 'call'; the assembler will replace "call #Subroutine" with "jmpret #Subroutine_ret, #Subroutine", and replace "ret" with "jmp #0" (during runtime, the "#0" will be replaced with "#(Main_code+1)" by the call (jmpret) instruction). Note also that you never need to refer to "_ret" in the caller code; it is hardcoded into the assembler.

    Edit: I used a colon at the end of the labels, which is not required in SPIN PASM, and normally not used, although it also works. I use it because I program in GCC PASM, and I've noticed that if I want to indent the label (sometimes I do this to make nested loops more clear), it will only work if there is a colon appended to the label.
  • AribaAriba Posts: 2,690
    Here is a different test methode:
    :keep_checking  test	PIN24, ina  wc          'Get the current inputs
      	if_c	call	#On_Signal_Base_int
      	if_nc	call	#Off_Signal_Base_int
    
    		test	Pin26, ina  wc
      	if_c	call	#On_Signal_Hopper_int
      	if_nc	call	#Off_Signal_Hopper_int
           
                    jmp	#:keep_checking
    
    
    Off_Signal_Base_int    
                            mov     Time, cnt      
                            add     Time, Period200us
    Off_Signal_Base         waitcnt Time, #14        
                            xor 	outa, Pin2
                            waitcnt Time,#12
                            xor 	outa, Pin2
                            waitcnt Time,#24
                            xor 	outa, Pin2
                            waitcnt Time,#24
                            xor 	outa, Pin2
                            waitcnt Time,#49
                            xor 	outa, Pin2
                            waitcnt Time, #49
                            xor 	outa, Pin2
                            waitcnt Time, #24
                            xor 	outa, Pin2
                            waitcnt Time, #24
                            xor 	outa, Pin2
    Off_Signal_Base_int_ret
    Off_Signal_Base_ret	ret
    
    		...
    
    Pin2			long	1<<2
    Pin24			long	1<<24
    Pin26			long	1<<26
    

    Andy
  • Hello,
    thanks for the info, I modified it to this:
                   test     Just_input_pin24, ina   wz          ' test for pin 24
                    if_z      jmpret :Off_Signal_Base_ret,#:Off_Signal_Base_int    
                    if_nz     jmpret :On_Signal_Base_ret,#:On_Signal_Base_int       
    '                
    '
                    test     Just_input_pin26, ina   wz          'test for pin 26
                    if_z      jmpret :Off_Signal_Hopper_ret,#:Off_Signal_Hopper_int    
                    if_nz     jmpret :On_Signal_Hopper_ret,#:On_Signal_Hopper_int
    

    and it seems to work,

    regards
    Jeff
  • Hello,

    This is the final working version of the code:
    
    CON
      _CLKMODE = xtal1 + pll16x
      _XINFREQ = 6_200_000
    
    
    PUB main
    
      cognew(@lfs_heater, 0) ' Start a Cog with our assembly routine, no stack
                        ' is required since PASM requires we explicitly
                        ' assign and use memory locations within the Cog/Hub
    DAT
            org     0
    LFS_heater      mov     dira, Both_P2_P5_output'   Pin24       ' Set our Pin to an output
                    mov     outa,Both_P2_P5_low 
                    rdlong  Delay,  #0
     
    :keep_checking
    
                    test      Just_input_pin24,ina   wz          ' test for pin 24
                    if_z      call #Off_Signal_Base    
                    if_nz     call #On_Signal_Base       
    '                
    '
                    test     Just_input_pin26, ina   wz          'test for pin 26
                    if_z      call #Off_Signal_Hopper    
                    if_nz     call #On_Signal_Hopper        
                    
                    jmp#:keep_checking
    
    Off_Signal_Base   
                            mov     Time,   cnt       ' Prime our timer with the current value of the system counter
                            add     Time,   Period200us       ' Add a minimum delay ( more on this below )
                            waitcnt Time, #14     ' Start waiting       
                            xor outa, Pin2
                            waitcnt       Time,#12
                            xor outa, Pin2
                            waitcnt       Time,#24
                            xor outa, Pin2
                            waitcnt       Time,#24
                            xor outa, Pin2
                            waitcnt       Time,#49
                            xor outa, Pin2
                            waitcnt       Time, #49
                            xor outa, Pin2
                            waitcnt       Time, #24
                            xor outa, Pin2
                            waitcnt       Time, #24
                            xor outa, Pin2
    Off_Signal_Base_ret     ret
    
    
    Off_Signal_Hopper
                            mov     Time,   cnt       ' Prime our timer with the current value of the system counter
                            add     Time,   Period200us       ' Add a minimum delay ( more on this below )
                            waitcnt Time, #14     ' Start waiting       
                            xor outa, Pin5
                            waitcnt       Time,#12
                            xor outa, Pin5
                            waitcnt       Time,#24
                            xor outa, Pin5
                            waitcnt       Time,#24
                            xor outa, Pin5
                            waitcnt       Time,#49
                            xor outa, Pin5
                            waitcnt       Time, #49
                            xor outa, Pin5
                            waitcnt       Time, #24
                            xor outa, Pin5
                             waitcnt       Time, #24
                            xor outa, Pin5
    Off_Signal_Hopper_ret   ret
    
    On_Signal_Base
                            mov     Time,   cnt       ' Prime our timer with the current value of the system counter
                            add     Time,  Period200us     ' Add a minimum delay ( more on this below )        
                            waitcnt Time,   #10       ' Start waiting
                            xor outa, Pin2   
                            waitcnt       Time,#40      
                            xor outa, Pin2 
                            waitcnt       Time,#75
                            xor outa, Pin2 
                            waitcnt       Time,#50  
                            xor outa, Pin2  
                            waitcnt       Time,#25 
                            xor outa, Pin2  
                            waitcnt       Time,#25
                            xor outa, Pin2
    On_Signal_Base_ret     ret
    
    On_Signal_Hopper        mov     Time,   cnt       ' Prime our timer with the current value of the system counter
                            add     Time,   Period200us        ' Add a minimum delay ( more on this below )        
                            waitcnt Time,  #10      ' Start waiting
                            xor outa, Pin5   
                            waitcnt       Time,#40     
                            xor outa, Pin5 
                            waitcnt       Time,#75 
                            xor outa, Pin5 
                            waitcnt       Time,#50   
                            xor outa, Pin5  
                            waitcnt       Time,#25 
                            xor outa, Pin5  
                            waitcnt       Time,#25
                            xor outa, Pin5
    On_Signal_Hopper_ret   ret                        
                          
    
    Pin2    long    |< 2     ' Encde PIN to a bit mask
    Pin5    long    |< 5     ' Encde PIN to a bit mask    
    Period200us     long  20000 '  200  us
    Input_2_5_Mask  long      %00000000_0010_0100
    Just_input_pin24   long   %00000001_00000000_00000000_00000000
    Just_input_pin26   long   %00000100_00000000_00000000_00000000
    Both_P2_P5_output  long   %00000000_00000000_00000000_00100100
    Both_P2_P5_low     long   %00000000_00000000_00000000_00000000                                    
    temp1 long 0          
    Delay           res     1
    Time            res     1
    FIT 496
    
    
  • ChrisGaddChrisGadd Posts: 310
    edited 2016-03-03 20:24
    Will there ever be a situation where pin 24 and pin 26 are both high or both low, and will that cause a problem?
    Here's another way to test, keeping more in line with the comments of just one or the other:
    LFS_heater
                            or        dira,p2_p5_mask
    :loop
                            mov       temp1,ina
                            test      temp1,p24_p26_mask     wc      ' C is cleared if both low or both high                                
              if_nc         jmp       #:loop                                                                                                
                            test      temp1,p24_mask         wc      ' C is set if P24 high, P26 low                                        
              if_c          jmp       #:base_on_hopper_off                                                                                   
    :base_off_hopper_on                                                                                                                     
                            call      #Off_Signal_Base                    
                            call      #On_Signal_Hopper                            
                            jmp       #:loop
    :base_on_hopper_off
                            call      #On_Signal_Base                               
                            call      #Off_Signal_Hopper                            
                            jmp       #:loop
    
Sign In or Register to comment.