Shop OBEX P1 Docs P2 Docs Learn Events
Remote Control Props: — Parallax Forums

Remote Control Props:

JMLStamp2pJMLStamp2p Posts: 259
edited 2008-03-28 17:52 in Propeller 1
Hello Paul,
I have narrowed my problem down somewhat. I have (2) attached "Spin" Files:

1) Sloss_Keypad_Input_3_08_Final····· 'Transmitter End
2) Sloss_Keypad_Input_3_08_Rx_Fix··· 'Receiver End

If I load my Transmitter and Receiver props with the associated code above. The Transmitter code for the transmitting Prop and the Receiver code for the receiver Prop I can send the numbers and everything works perfect every time, from the transmitter to the receiver.

I am trying to write one program that I can run in both props to transmit & recieve which is the ·( Sloss_Keypad_Input_3_08_Final )·file. It is actually a·combonation of the "2" files. I have the rxStr method written so that
if I press the "Star" button on my (4 by4) matrix Keypad it will go to the Receive_Loop Method and simulate the file that works every time, the "Sloss_Keypad_Input_3_08_Rx_Fix"·file. When I have the receive Prop go to this method and then transmit 3 sets of Three digit numbers from the transmitting end this is what happens. The Recieving end gets the 9 digits but does not increment the LCD cursor as it does when I run the "Sloss_Keypad_Input_3_08_Rx_Fix" alone in the recieve Prop. The First location in the LCD displays all the digits sent but "1" at a time in location Col-18, Row-2 on my LCD. For some reason I am having a real problem figuring out
what is causing this, I actually copied and pasted the exact code in the working file to the non working section of "Sloss_Keypad_Input_3_08_Final"·which is the "Receive_Loop" method.

I am putting a tremendous amount of time into·my study of·Spin as I can see
the potential of using the Prop as an "Instrumentation Processor" at·our plant. I appreciate all the help in the forum but have found that there are times you can do all the studying you possibly·can from the Prop manual, look at all the examples for "newbees" and still need the help of a seasoned programmer.·It's like a puzzle sometimes all the pieces start looking the same :>)
If You would be so kind as to help with this part of my project it would be greatly appreciated.

Sincerely,
John Logan
Sloss Industries
JMLStamp2p


<edit> took the Attn: from subject line.







Post Edited By Moderator (Paul Baker (Parallax)) : 3/22/2008 8:48:40 PM GMT
«13

Comments

  • tpw_mantpw_man Posts: 276
    edited 2008-03-08 21:02
    If you are wanting to talk to a specific person, you probably should use PM to do that. Blah etc. Atn some person is not really appropriate. It also implies that you do not want other people to help you. Perhaps you guys can exchange e-mail or something over PM.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    I am 1010, so be surprised!
  • JMLStamp2pJMLStamp2p Posts: 259
    edited 2008-03-08 22:55
    tpw_man,
    Forgive me if it came across that way, I have not had many people that were willing to respond to what I am trying to do. I will
    check out the private e-mail. And if you like I would love for you to look at the code posted.
    Regards,
    JMLStamp2p
  • deSilvadeSilva Posts: 2,967
    edited 2008-03-09 07:26
    @TPW-MAN
    It is not possible to send attachements by PM...
    I did not understand it the way that people should be excluded, but that this needs not immediate attention from deSilva (which generally makes me respire)
  • hippyhippy Posts: 1,981
    edited 2008-03-09 15:03
    @ JMLStamp2p : I'm afraid I don't have the time to go through your code, understand it nor debug it, but this did jump out at me, and it will likely cause you some problem in the future ...

    PUB Receive_Loop
      LCD_Setup  
      Recieved_Data(9,@datain)
      Print_Status_to_LCD
      Receive_Loop
    
    
    



    You have a recursive call of Receive_Loop calling itself and that will ultimately cause 'bad things' to happen.

    I think this is one of those cases where you've strayed a little too far out of your depth and are trying to bash something into shape without having something which can be bashed into shape.

    You have quite a complex configuration which is hard for you to debug and for anyone else to follow if they do not have the time to put into investigating all you've done and are trying to do. What I do in such cases is strip out everything which could be causing a problem and get back to the bare basics. In this case get inter-Propeller comms working without the complexity of scanning keypads, passing over multi-digit numbers and all the encoding and decoding used there. Have one send a known sequence of characters, say one a second and have the other put them on the LCD. Get that working then start moving the code forward to re-introduce sending multi-digit numbers, key-scanning and so on a step at a time.

    Unless you've got good foundations the rest will always be wobbly and in danger of collapse.

    I also find it invaluable to have some sort of debugging mechanism, either the TV_Text display or serial output to a terminal emulator, so I can put 'print statements' in the code to see where execution is going and check whether variables hold the values I expect or not. When it all goes wrong ( and it invariably does ), it's a sometimes long and arduous task of trying to determine what is happening compared to what should be happening and then having to determine why there is a difference to what was expected. It's usually the original programmer best equipped to do that as they most intimately understand what the code should be doing. Others can look at the code, spot obvious problems ( as above ), but most often it is down to the programmer themselves to do the necessary debugging.
  • JMLStamp2pJMLStamp2p Posts: 259
    edited 2008-03-09 17:09
    Hippy, Good advice and I will do exactly that. I do have the RF section working and I can display three sets of three digit numbers
    on it every time, so thats a start. I understand about using the LCD as a debug tool and will try and incorperate it a little more than I've done.
    Thanks for the advice,
    JMLStamp2p
  • hippyhippy Posts: 1,981
    edited 2008-03-09 18:07
    Debugging can be one of the most frustrating, time-consuming and soul destroying tasks a programmer faces and it's pointless to deny that, but it does get easier as one gets used to it, accepts it as a fact of life, and develops an insight into what one is looking for.

    Narrowing the code down to where something is going wrong is key. Once you find a place where something is wrong, it then means working backwards to discover how that could be and ultimately what's causing that.

    Some people seem to have a better disposition to debugging than others. I find it invaluable to step away from the problem and think about why something could be happening then come back and check to see how my theory matches with what is really happening.
  • deSilvadeSilva Posts: 2,967
    edited 2008-03-09 18:26
    I have worked with safety critical systems.... Sometimes I needed a "proof" that things worked as specified. Compared to that, "debugging" is pure joy smile.gif
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-03-09 18:44
    The biggest roadblock for new programmers to overcome in debugging is the tendency to justify what they've written (i.e. "This should work."), rather than to look dispassionately for what's not right in their code. But more important still is to develop an incremental, code-and-test programming style that minimizes the necessity for debugging to begin with. In other words, if you're chasing down a bug that was introduced more than a few hours ago, you probably need to reexamine your coding technique.

    -Phil

    Post Edited (Phil Pilgrim (PhiPi)) : 3/9/2008 6:49:43 PM GMT
  • hippyhippy Posts: 1,981
    edited 2008-03-09 19:15
    Sod's law also tells us that the bug is not always where we see its symptoms but can be somewhere else entirely. Getting too focused on where the problem is or "must be" makes one miss where it really is - If a display isn't showing the right value, is the right value even being obtained in the first place ?
  • Graham StablerGraham Stabler Posts: 2,510
    edited 2008-03-09 19:29
    And just when you learn that yo get two bugs at once
  • JMLStamp2pJMLStamp2p Posts: 259
    edited 2008-03-10 13:34
    Thanks for the suggestion guys, I have spent the last two days going over the Spin manual and have learned alot. Not that I haven't spent time in it already for some reason things are starting to "Click" :>) Would you guys look at the following Flow and tell me if this should work:


    ········ cognew(rxStr(9, @datain), @ rsStr_Stack)
    ·········cognew(Received_Data(9,@datain_2), @ RD_Stack
    ·······
    ·········data.stop
    ·········data.start((1,0,%0010,9600)

    ·········data_LCD.stop
    ·········data_LCD.start(3,2,0,19200)

    ·········LCD_Setup

    ·········repeat
    ············· rxStr(9, @datain)
    ··············Received_Data(9,@datain_2)
    ·········
    ·········

    rxStr & Received_Data both make calls to FullDuplexSerial via the cogs started above. Both methods wait for
    "9" numbers to be entered "rxStr via the Keypad and "Received_Data" via the tranceiver. After these "9" numbers are entered in let say the rsStr method I want it to loop inside itself so to speak and go back for another 9 numbers. I want it to do this·without interupting the Received_Data method that is doing the same thing at the same time. While doing this if either method receives "9" bytes then I want it to go to the "Print_Status_To_LCD method to display the numbers entered and then to the Transmit_Data method to transmit them to the remote Prop. After doing this I want it to return to the repeat loop, is their a problem doing this as long as I make sure that I have "return statments" at the end of each method called ?
    JMLStamp2p
  • JMLStamp2pJMLStamp2p Posts: 259
    edited 2008-03-10 13:35
    Typo ...
    Note: Did not list

    cognew(rxStr(9, @datain), @ rsStr_Stack)
    cognew(Received_Data(9,@datain_2), @ RD_Stack)

    data.stop
    data.start((1,0,%0010,9600)

    data_LCD.stop
    data_LCD.start(3,2,0,19200)

    LCD_Setup

    repeat
    rxStr(9, @datain)
    Received_Data(9,@datain_2)
  • JMLStamp2pJMLStamp2p Posts: 259
    edited 2008-03-10 14:02
    Sorry guys, I havegot to learn to "Post Reply" :>)
    I have the following questions:

    1)What precautions should I take when using arrays, other than the size and declaration ?
    2)I believe that the "return" statement "Pops" data off the Stack that has been put there due
    to a method call, is this correct ? And is there anything else that I should be aware of as far as seperate stacks for each cog ?
  • Paul BakerPaul Baker Posts: 6,351
    edited 2008-03-10 21:36
    Heya John, am I correct that you figured out your original issue?

    To answer your recent questions,

    The code you posted won't work quite like you expect, At the start you call them into new cogs, the following code is immediately executed regardless what is going on in the two cogs. Then you go and call the two routines again, but this time you are calling one at a time, they execute in the current cog then the next one runs, but they do not run simultaneously. Typically the way you would program the subfunctions rxStr and Received_Data is to have them continue to run executiing thier code. If you have a situation where your top level program and subfunctions need to comminicate, you assign a memory location to serve as a sort of a mailbox to send messages. Coded this way, your main program's repeat loop would be empty. I haven't looked at the subfunctions, so I don't know if they are performing as you expect, but if not I can take a look at them.

    Really the only thing you need to deal with arrays is the start address and the number of elements.
    A spin routine's return value is on the stack and is returned when called for.

    PS, if you want to edit a post, just click on the pencil icon of the post.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.
  • JMLStamp2pJMLStamp2p Posts: 259
    edited 2008-03-11 04:22
    Hi Paul, Thank You for your reply. I understand what you are saying about starting the cogs and executing that code immediatly.
    What I am not clear on is how to make Recieved_Data and rxStr run at the same time both looping independantly of each other.
    Is it as simple as having a nested repeat loop in each method? I understanding that starting new Cogs causes them to run in Parallel but as soon as either one has received "9" digits it is going back to main and halting, is it not ? I could really use an example of this code. I believe that I can handle the other methods if I can just get this in my Head :>)
    JMLStamp2p
    John.
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-11 06:49
    How on earth did you get the forum to not eat the spaces in your posts above?

    First you need to remove this from main
    repeat
                  rxStr(9, @datain)
                  Received_Data(9,@datain_2)
    


    Than you need to make sure that rxStr and Received_Data not return. If you have a return in them than the new cogs will run through for 9 digits and then stop. In pseudo code this is what you want to do
    PUB rxStr
      repeat                                               'loop forever
        get Char                                          'get a character. this could be from your keypad or one of the serial ports and you are already doing this
        save Char Into Array                        'you are already doing this in some code
        if array is full                                    'you are already doing this in some code
          wait for serial to be free                  'this will be something new. Since both cogs could call the serial object at the same time bad things could happen
                                                               'get it working with rxStr and Received_Data separately and then you will need to learn about locks
          send data on serial port                   'you do this already in some code
          clear array and reset any counters   'once you have sent the data there is no longer a need for it. You also need to set the counter you are using back to 0
    
    


    So 90% is done. smile.gif

    By the way, it is a good idea to develop pseudo code like this before you start programming. It will help you and it will help others find problems quicker if you post it along with your actual code.
  • JMLStamp2pJMLStamp2p Posts: 259
    edited 2008-03-11 21:16
    stevenmess, Thank You for your help. My rxStr method is working now, I have
    posted the working method below. I will have to add a line at the botton to
    clear the array before looping back which I plan to go over the it more tonight.
    It is running in its own Cog and looping as it should to get 9 digits. It resets
    the LCD and gets 9 more digits,ect. Tommorow I will make sure everything is
    correctly and will then add the Received_Data method to run its its own Cog.
    Thank You !!! Your help is Greatly appreciated ...
    JMLStamp2p


    PUB RxStr(Num_of_Chars,strPtr) : char
    ·repeat
    ·· char := data_LCD.rx

    ·· if Num_of_Chars == 9
    ····· data_LCD.tx(254)·····································
    ····· data_LCD.tx(71)··············
    ····· data_LCD.tx(5)
    ····· data_LCD.tx(2)
    ··
    ·· elseif Num_of_Chars == 8
    ········ data_LCD.tx(254)·····································
    ········ data_LCD.tx(71)··············
    ········ data_LCD.tx(6)
    ········ data_LCD.tx(2)
    ··
    ·· elseif Num_of_Chars == 7
    ········ data_LCD.tx(254)·····································
    ········ data_LCD.tx(71)··············
    ········ data_LCD.tx(7)
    ········ data_LCD.tx(2)

    ·· elseif Num_of_Chars == 6
    ········ data_LCD.tx(254)·····································
    ········ data_LCD.tx(71)··············
    ········ data_LCD.tx(5)
    ········ data_LCD.tx(3)
    ··
    ·· elseif Num_of_Chars == 5
    ········ data_LCD.tx(254)·····································
    ········ data_LCD.tx(71)··············
    ········ data_LCD.tx(6)
    ········ data_LCD.tx(3)··
    ·· elseif Num_of_Chars == 4
    ········ data_LCD.tx(254)·····································
    ········ data_LCD.tx(71)··············
    ········ data_LCD.tx(7)
    ········ data_LCD.tx(3)··

    ·· elseif Num_of_Chars == 3
    ········ data_LCD.tx(254)·····································
    ········ data_LCD.tx(71)··············
    ········ data_LCD.tx(5)
    ········ data_LCD.tx(4)
    ··
    ·· elseif Num_of_Chars == 2
    ········ data_LCD.tx(254)·····································
    ········ data_LCD.tx(71)··············
    ········ data_LCD.tx(6)
    ········ data_LCD.tx(4)··
    ·· elseif Num_of_Chars == 1
    ········ data_LCD.tx(254)·····································
    ········ data_LCD.tx(71)··············
    ········ data_LCD.tx(7)
    ········ data_LCD.tx(4)
    ········
    · '
    ·· elseif Num_of_Chars == 0··
    ····· 'byte[noparse][[/noparse] strPtr] := 0
    ·····
    ····· data_LCD.tx(254)
    ····· data_LCD.tx(84)
    · 'Turn Blinking Cursor off.

    ·· if char == (88)········
    ····· char := 1···········
    ····· data_LCD.dec(char)··
    ··························
    ·· if char == (83)···········
    ····· char := 2································
    ····· data_LCD.dec(char)··
    ·· if char == (78)············
    ····· char := 3·································
    ····· data_LCD.dec(char)
    ·· if char == (87)·······························································
    ····· char := 4·································
    ····· data_LCD.dec(char)
    ·····
    ·· if char == (82)······························································
    ····· char := 5·································
    ····· data_LCD.dec(char)
    ·· if char == (77)·······························································
    ····· char := 6·································
    ····· data_LCD.dec(char)
    ·· if char == (86)·······························································
    ····· char := 7·································
    ····· data_LCD.dec(char)
    ·· if char == (81)·······························································
    ····· char := 8·································
    ····· data_LCD.dec(char)
    ·····
    ·· if char == (76)·······························································
    ····· char := 9·································
    ····· data_LCD.dec(char)
    ·· if char == (80)·······························································
    ····· char := 0·································
    ····· data_LCD.dec(char)·····
    ·· if char == (73)·······························································
    ····· 'char := "A"·······························
    ····· data_LCD.tx(char)···········
    ····· data_LCD.tx(254)·····················
    ····· data_LCD.tx(88)··
    ·· if char == (72)·······························································
    ····· 'char := "B"·······························
    ····· data_LCD.tx(char)···········
    ····· data_LCD.tx(254)·····················
    ····· data_LCD.tx(88)
    ·····
    ·· if char == (71)·······························································
    ····· 'char := "C"·······························
    ····· data_LCD.tx(char)···········
    ····· data_LCD.tx(254)·····················
    ····· data_LCD.tx(88)
    ····
    ·· if char == (70)·······························································
    ····· 'char := "D"··
    ·· if char == (70)·············
    ····· data_LCD.tx(254)···················
    ····· data_LCD.tx(88)
    ·····
    ·· byte[noparse][[/noparse]strPtr++] := char
    · 'Save byte & increment array pointer.
    ··
    ·· if Num_of_chars -- == 1
    ··· 'Have we received 9 Digits ? if not loop back.
    ··· 'If we have received 9 digits execute indented code.·······
    ·····························
    ····· Print_Status_To_LCD(@rxStr_array)················
    ····· Transmit_Timer_values(@rxStr_array)
    ····· byte[noparse][[/noparse]strPtr]:= 0
    ····· LCD_Setup
    ····· Num_of_Chars := 9····
    ·····
  • Paul BakerPaul Baker Posts: 6,351
    edited 2008-03-11 23:21
    Excellent, glad you found a solution.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-12 07:19
    Glad you got it working. Just a couple of suggestions. Use a case statement instead of all the 'if's. It will be a bit easier to read and should also run a bit faster. Also, this
    data_LCD.tx(254)                                      
    data_LCD.tx(71)
    


    appears to be in every if statement in the first part of your program. Why not just do it at the beginning and you will save some space in the hub.
  • StefanL38StefanL38 Posts: 2,292
    edited 2008-03-12 09:24
    Hello John,

    i have a question to understand your RxStr-method right

    as soon as a byte is received by

    char := data_LCD.rx

    you send a byte to the LCD

    by

    if char == (88)
    char := 1
    data_LCD.dec(char)
    etc.

    and if you have received 9 digits
    you call the methods

    Print_Status_To_LCD(@rxStr_array)
    Transmit_Timer_values(@rxStr_array)

    what's the difference between the single bytes sended to the lcd by

    if char == (88)
    char := 1
    data_LCD.dec(char)
    etc.

    and the method
    Print_Status_To_LCD(@rxStr_array) ?

    Do you have a LCD with 2 rows ?

    one row showing the Input from the keypad and the other showing the actual received serial data?

    regards

    Stefan
  • JMLStamp2pJMLStamp2p Posts: 259
    edited 2008-03-12 12:43
    Hello, you ask about ...

    what's the difference between the single bytes sent to the lcd by

    if char == (88)
    char := 1
    data_LCD.dec(char)
    etc.

    This is setting the local varible "char" to the dec. value "1" of course. My LCD

    outputs "88" when I press the digit "1" so I am converting it to "1" to correspond to

    the digit that I pressed. The LCD is a 4 by 20 by Matrix Orbital, has programmable

    outputs, a direct keypad interface and debouncing built in, Parallax sell it.


    I have a question: My rxStr method is running fine but when I transmit out the 2nd

    set of numbers to the LCD, the recieving end shows the last set that I had sent.

    If I press the reset button on my transmitting end where our rxStr method is

    running and transmit 9 more digits the updtated set of numbers show on the

    receiving end. It looks like my array is not being cleared·in my rxStr method.

    Here is the code: I am trying to use bytefill to clear the array and byte[noparse][[/noparse]strPtr]:= 0

    to reset the array pointer back to location "0" but still having the problem,

    What am I missing?



    ·if Num_of_chars -- == 1
    ··· 'Have we received 9 Digits ? if not loop back.
    ··· 'If we have received 9 digits execute indented code.·······
    ·····························
    ····· Print_Status_To_LCD(@rxStr_array)················
    ····· Transmit_Timer_values(@rxStr_array)
    ····· byte[noparse][[/noparse]strPtr]:= 0
    ····· bytefill(@rxStr_array,0,9)
    ····· LCD_Setup
    ····· Num_of_Chars := 9

    Regards,

    JMLStamp2p
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-12 21:01
    Unfortunately this is going to require a few changes to you method. The problem is that you are not actually setting the pointer (strPtr) back to the start of the array. The line
    byte[noparse][[/noparse]strPtr]:=0
    

    only makes the last element in the array 0!

    So here is what you need to do. Don't change strPtr anywhere in the method. Leave it the same so that we always know where the array starts. Also, it would be a good idea to do the same thing with Num_of_Chars. Than you will need a local variable named something like count. When you write a byte to the array simple do this
    byte[noparse][[/noparse]strPtr][noparse][[/noparse]count++]:=char
    


    Than you just need to check what count is compared to Num_of_Chars and reset count to 0 to start at the beginning of the array again. You will also need to make count 0 at the start of the method as it may not be initialised to zero.
  • JMLStamp2pJMLStamp2p Posts: 259
    edited 2008-03-12 21:56
    Could I just simply do this:

    byte strPtr[noparse][[/noparse]0] :=0
    byte strPtr :=0
    byte strPtr :=0
    byte strPtr :=0
    ect.

    I have tried: bytefill(@strPtr,0,9) but it doesn't work either.
    JMLStamp2p
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-12 22:32
    JMLStamp2p said...
    byte strPtr[noparse][[/noparse] 0] :=0
    byte strPtr[noparse][[/noparse] 1] :=0
    byte strPtr[noparse][[/noparse] 2] :=0
    byte strPtr[noparse][[/noparse] 3] :=0
    ect.

    I have tried: bytefill(@strPtr,0,9) but it doesn't work either.
    JMLStamp2p

    The forum ate some of you array indexes so here they are again. smile.gif

    strPtr is a long on the stack that contains a pointer to the start of an array. You could do that but you will need the brackets around 'strPtr' like in my last post. However, it will be quicker to do bytefill(strPtr,0,9), but, this will only work if strPtr is the start of the array and you don't change it.

    I presume that you have used the stamps from your name. Do the stamps have pointers or not or have you used them before? If not than I will try to explain a little about them.
  • Paul BakerPaul Baker Posts: 6,351
    edited 2008-03-12 22:35
    bytefill requires a pointer for both source and destination, therefore bytefill(@strPtr, 0 , 9) takes the 9 bytes located at addresses 0-9 and copies them to the location starting at strPtr.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-12 22:46
    Paul, were you thinking of bytemove?
  • JMLStamp2pJMLStamp2p Posts: 259
    edited 2008-03-12 22:47
    stevenmess. The following works but will this eat up memory ?


    if Num_of_chars -- == 1
    'Have we received 9 Digits ? if not loop back.
    'If we have received 9 digits execute indented code.

    Print_Status_To_LCD(@rxStr_array)
    Transmit_Timer_values(@rxStr_array)
    LCD_Setup
    data.rxflush
    data_LCD.rxflush
    byte[noparse][[/noparse] strPtr]:= 0 'Are you saying that this should be: "long[noparse][[/noparse] strPtr]:= 0"
    bytefill(@rxStr_array,0,9)
    RxStr(9,@rxStr_array) 'Calling the method again.

    I was thinking that after "bytefill(@rxStr_array,0,9)" the program would go back to "char := data_LCD.rx" get
    more bytes and write over the array contents even if they were not cleared. I need some help understand the
    pass by ref. thing I guess.
  • Paul BakerPaul Baker Posts: 6,351
    edited 2008-03-12 23:18
    Steven, yes you are correct, sorry for the error.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-03-12 23:25
    Yes, it will eat up memorysmile.gif

    In programming there is a thing called recursion. Recursion simply means that a method calls itself. For example
    PUB doSomething(x,y)
      doSomething(y,x)
    


    In theory, if you call doSomething it will call itself with x and y switched, and then call itself again, and again and again......

    However, this won't actually happen. In the propeller (actually most computers) there is an area of memory that is called the stack. A stack is useful for all kinds of things like storing local variables, return values and various other things. The stack works kind of like a stack of paper on your desk. You can push things onto it (like putting a piece of paper on your deck) or pop things off it (like getting the top piece of paper off the stack on your deck). Now, every time you call a method in spin, the interpreter puts (pushes) several things on the stack. Some of these are used by the spin interpreter so that it knows where to come back to when it is finished the method (I think that there are 3 longs but I'm not sure). It also puts space for every argument that the method has, the return value and any local variables.

    So, every time that we call the doSomething method above we are pushing 3 longs for the interpreter+1 long for the return value+2 arguments. This comes to a total of 6 longs every time we call this method! Now, to go back to the paper on you desk analogy, what will happen if you put things onto your desk and never take them off? Of course the pile of papers will get so high that you will not be able to put more on or the stack will fall over. The same thing is happening in this example. We are pushing 6 longs onto the stack every time we call doSomething, we are never taking anything off and we go into a loop that we can't get out of. So eventually you will use up all the RAM in your propeller. Once you have used up all the RAM your propeller will go back to the start of the RAM and write over some important settings.

    So what can we do and is recursion still useful?
    Consider this code
    PUB foo(x)
      if x=0
        return
      else
        foo(x-1)
        return
    


    Now, this code is slightly different. It has a return in it. This means that if the condition x=0 is ever true than we will stop calling foo. We know this will eventually happen because every time we call foo we are calling it with 1 less than before. So if we called foo with x=3 what would happen? The table below shows the stack size and the value of x
    x Stack size
    3 5
    2 10
    1 15
    0 20
    But now x=0 so we don't call foo anymore. This is exactly what we want. The stack will have a maximum size of 20 and then start shrinking as all the methods return. And yes, this is useful for many things although I haven't shown an example that does anything useful.

    Well, that was a lot more than I meant to type and I haven't really answered any of your questions yet. So
    What you are doing in your post above is the basically the same as doSomething above. You call RxStr over and over, constantly pushing data onto the stack but never taking any off. Eventually you will run out of memory and bad things will happen to your program because you are writing data over the top of something else or the ROM.

    I'll talk a bit about pointers and passing by reference in my next post and hopefully I can make it shorter than this one smile.gif
  • JMLStamp2pJMLStamp2p Posts: 259
    edited 2008-03-13 15:36
    stevenmess,

    The complete working code is attached via file, It is working just exactly like I want it to.
    The keypads and tranceivers are running in their own Cogs and two seperate serial ports
    are set up at diggerent baud rates. I had to call the Received_Data·AND rXStr methods
    inside themselves for it to work so please give me your opinion as far as memory goes. I don't
    want to be eating it up and have problems later on. Thank You so much for all the help you are giving me.
    JMLStamp2p
Sign In or Register to comment.