Shop OBEX P1 Docs P2 Docs Learn Events
Simple Assembly Language Quesiton — Parallax Forums

Simple Assembly Language Quesiton

tom90tom90 Posts: 55
edited 2007-10-30 15:28 in Propeller 1
How do I read information from a pin in Assembly Language?

I am trying to send out a simple square wave on one pin, and read it with another pin.
After the second pin reads in the info, I want to send it to a third pin to output it again.
Just a simple exercise to try and better learn assembler.

I got the square wave to work just fine, but I cant get the second pin to read in the info.

I tried using something like

andn dira, pin 'sets the pin to an input
mov ina, pin 'trying to read the info coming in on the pin (didn't work)


How do I read in this information so that i can pass it to another pin to be output again?
I would assume I have to store it in a variable somehow...if this is the case, can I read
it in and store it in a variable all in one step?

Thanks
Tom

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2007-10-16 15:17
    INA is a register with the input states of all the I/O pins. It has to appear as a source operand in an instruction. You can do a:
    MOV temp,INA
    and then test one or more bits in temp or you can do:
    TEST pin,INA WC
    This will use the bitmask "pin" to test the INA register and set the C flag if the result is non-zero.
  • Ken PetersonKen Peterson Posts: 806
    edited 2007-10-16 15:18
    You can do the following:

    mov mask, #1
    shl mask, pin
    test mask, ina wz

    if the pin is low, the zero flag will be set. You will of course have to define a long for "mask".·

    I'm sure there's probably an easier way.· I guess I assumed "pin" had the pin number rather than a mask.· The first two instructions create a mask from the pin number.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    The more I know, the more I know I don't know.· Is this what they call Wisdom?

    Post Edited (Ken Peterson) : 10/16/2007 3:23:15 PM GMT
  • tom90tom90 Posts: 55
    edited 2007-10-16 15:47
    First of all, when i wrote "pin" i did mean a mask

    Second, These flags are very new to me, so please bare with me.

    When I set these flags, How do i use the information on the next cog when i want to output that signal again?
    I wanted this operation to be in a separate cog as the one that reads in the information. How will this work if I
    am reading in 8 bits, for example

    test mask, ina WC
    test mask, ina WC
    test mask, ina WC
    test mask, ina WC
    test mask, ina WC
    test mask, ina WC
    test mask, ina WC
    test mask, ina WC
    jmp #:loop

    can I alter the C flag eight times in a row and still be able to read it properly in the other cog? How do I read it in the other cog?

    if_nc andn outa, pin
    if_c mov outa, pin

    Would this be correct?

    Thanks for all the help
    Tom
  • AribaAriba Posts: 2,685
    edited 2007-10-17 19:13
    Tom

    The Z and C Flags are part of the CPU in a COG. They are needed to do conditional execution of following instructions.
    Another COG has a totally independent CPU with its own flags. You cannot read the flags of another Cog.
    This Flags exists only 1 time in every Cog, if you do 8 times 'test mask,ina WC' then the C-flag is overwritten every time.

    If one Cog have to read a value from another Cog you normally go over the Hub-RAM. One Cog writes the value to the HubRAM with wrbyte (/word/long), and the other Cog can read it from the HubRAM with rdbyte(/word/long).
    But especially for Pins this is not necessary, because all Cogs has parallel access to the pins.

    So for your test program, you can read a pin in one Cog and set a second pin according to the state of the fist pin. Then a second Cog can read this second pin and set a third pin according to the second. A good Assembly instruction to set 1 ore more pins according a state of a flag is MUXC and MUXZ:

    test firstpinmask,ina WZ 'Test the pin and set the Z flag to its state (inversed: Z is 1 if pin=0, and 0 if pin=1)
    muxnz outa,secondpinmask 'Set the second pin to the invers state of Z flag


    Andy
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2007-10-17 19:52
  • tom90tom90 Posts: 55
    edited 2007-10-19 18:42
    Hey Guys I finally got this thing working.

    MUXNZ did the trick

    Thanks for all the help,
    Tom
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-19 19:13
    What you write is quite improbable. I like MUX very much, but it can't do wonders. Maybe you will post your code and tell what you intended to do?
  • Ken PetersonKen Peterson Posts: 806
    edited 2007-10-19 23:00
    @deSilva: don't be so negative! Wait and see how it was done before saying it won't work. I'm sure I've been surprised to see things work even when done in unorthodox ways. I do admit it is hard to imagine how to read a pin using MUXNZ.

    I think it's something like this:

    test mask1, ina wz
    muxnz outa, mask2

    right?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    The more I know, the more I know I don't know.· Is this what they call Wisdom?

    Post Edited (Ken Peterson) : 10/19/2007 11:10:12 PM GMT
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-19 23:13
    He had a multi-COG issue....
    He doesn't need flags in the first place.....
  • Ken PetersonKen Peterson Posts: 806
    edited 2007-10-19 23:22
    I didn't see anything in the original question about having to use more than one cog. If you can do it in one cog, why use more?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    The more I know, the more I know I don't know.· Is this what they call Wisdom?
  • Mike GreenMike Green Posts: 23,101
    edited 2007-10-23 13:32
    Two cogs can be synchronized by having both wait for the same system clock value. Simply compute a future system clock value, far enough in the future so the two cogs can complete their initialization, then do a WAITCNT in each cog on the same value. The WAITCNTs will complete at the same time and the two cogs will remain in lock step until they do something to get out of sync (like wait for I/O or for a HUB access). The high resolution text VGA drivers are examples of this. They use from 2 to 6 synchronized cogs to get the processing bandwidth to produce the VGA video.
  • tom90tom90 Posts: 55
    edited 2007-10-23 20:45
    Thanks Mike. That is what i first had in mind but i guess i wasnt using the waitcnt correctly.

    I am also posting my code for those who wanted to see it.

    Thanks to all who have helped me so far.
    Tom
  • tom90tom90 Posts: 55
    edited 2007-10-25 15:29
    I am trying to get the two cogs to start at exactly the same time, but I still cant get it to work right. Am I using the waitcnts correctly? Will it automatically pass the variables "time" and "delay" to the other cog? When I look at this on the scope, the two signals still aren't matching up.

    Any Ideas?

    CON
      _clkmode = xtal1 + pll16x                          
      _xinfreq = 5_000_000
    
    PUB Main
     
      cognew(@reading, 0)
      cognew(@controlbyte, 0)
    
    DAT
                  ORG       0
    controlbyte   mov       time, cnt
                  add       time, #60
                  waitcnt   time, delay
                  mov       dira, pin6               
    :loop         mov       outa, pin6
                  nop      
                  andn      outa, pin6  
                  nop
                  mov       outa, pin6
                  nop       
                  andn      outa, pin6      
                  jmp       #:loop
                                                 
    pin6    long            |<6
    delay   long            80_000_000
    time                    res 1
    
    DAT
                  ORG       0
    reading       waitcnt   time, delay
                  mov       dira, pin2
    :loop1        mov       outa, pin2
                  nop
                  andn      outa, pin2
                  nop
                  mov       outa, pin2
                  nop
                  andn      outa, pin2
                  jmp       #:loop1
    pin2    long            |<2
    
    
    



    Thanks again,
    Tom
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-25 17:48
    You must not use any variable in another COG ("time") It is pity that the compilr does not warn you, as it in fact could...

    "time" is allocated in COG "conrolbyte".
    COG "reading" accessses an arbitrary cell allocated where "time" would be in the other COG.

    A workaround will be to make the main program set a time stamp both COGS can sync to. BE careful to not set this time stamp before both COGs are working...
  • tom90tom90 Posts: 55
    edited 2007-10-30 14:51
    Desilva,

    If I set the variables "time" and "delay" in the main program, how do I pass those variables to the the waitcnt statements in the two cogs running assembly?
    Mike Green said...
    Two cogs can be synchronized by having both wait for the same system clock value. Simply compute a future system clock value, far enough in the future so the two cogs can complete their initialization, then do a WAITCNT in each cog on the same value.

    I think you and mike are talking about the same thing, but I'm not quite getting it to work.

    Thanks
  • Mike GreenMike Green Posts: 23,101
    edited 2007-10-30 15:14
    Here's an example using your code.
    CON
      _clkmode = xtal1 + pll16x                          
      _xinfreq = 5_000_000
    
    VAR
      long time
    
    PUB Main
      time := 0
      cognew(@reading, @time)
      cognew(@control, @time)
      waitcnt(clkfreq/200 + cnt)               ' Wait 5ms for both cogs to start
      time := (clkfreq/1000 + cnt) #> 1   ' Both will sync about 1ms later
    ' Because of the way the code is written, make sure new time is not zero
    
    DAT
                  ORG       0
    control   rdlong    temp1,par      ' Wait for value to be non-zero
                  tjz       temp1,#control
                  waitcnt   temp1,#0       ' Wait for synchronization point
                  mov       dira, pin6               
    :loop       mov       outa, pin6
                  nop      
                  andn      outa, pin6  
                  nop
                  mov       outa, pin6
                  nop       
                  andn      outa, pin6      
                  jmp       #:loop
                                                 
    pin6        long      |<6
    temp1     res       1
    
    DAT
                  ORG       0
    reading   rdlong    temp2,par     ' Wait for value to be non-zero
                  tjz       temp2,#reading
                  waitcnt   temp2,#0      ' Wait for synchronization point
                  mov       dira, pin2
    :loop1     mov       outa, pin2
                  nop
                  andn      outa, pin2
                  nop
                  mov       outa, pin2
                  nop
                  andn      outa, pin2
                  jmp       #:loop1
    pin2       long      |<2
    
    temp2    res       1
    
    

    Post Edited (Mike Green) : 10/30/2007 3:21:43 PM GMT
  • tom90tom90 Posts: 55
    edited 2007-10-30 15:28
    Hey Mike,
    That probably would have taken me years to figure out.

    Thanks for all your help!
    Tom
Sign In or Register to comment.