Help with GOSUB


Closed Thread
Results 1 to 17 of 17

Thread: Help with GOSUB

  1. #1
    Join Date
    Jul 2015
    Posts
    7

    Default Help with GOSUB

    Hi. First time post here. I'm using PIC Basic Pro, MPLAB ASSEM and a PIC16F870.
    Need some help with the GOSUB in my code.

    I'm telling a Compact Flash card that I want to read 256 sectors and then pulse
    RD low 65535 times to get the 16Bit data out. I do this 4 times because the whole
    file is 4 x 256 sectors.

    If I put the little REPEAT...UNTIL code after each call up of 256 sectors, the program
    works fine. I can push the start button as many time as I need for the whole file
    to be read from the compact flash card.

    If I use a GOSUB dat to go to the little dat: REPEAT...UNTIL RETURN pulse RD low routine,
    the program
    will only work about 4-5 times and then vapour locks. The RD pin keeps running
    (pulsing low) and doesn't stop after 65535 pluses. The code doesn't recover.

    Any ideas?

    Thanks
    Attached Files Attached Files

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,516


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Hi,
    My initial thought, since you're saying that it does work if you paste the content of the dat subroutine inplace of each GOSUB to TO the dat subroutine, was/is that it's a timing issue. I don't know anything about the timing requirements of a CF card but using that GOSUB does introduce a couple of extra instruction cycles for the jump to and from the routine.

    Then, when looking closer at the actual code for the dat subroutine:
    Code:
    dat:
       i = 0           'pulse RD low 65535 times
    REPEAT
       rd[i] = 1      '<----What is the purpose of this line?
       i = i + 1
       pulsout rd, 4   '44.1KHz Playback
    UNTIL i = 65535
    RETURN
    I'm wondering what you're trying to achieve with the rd[i]=1, specifically the [i] part, when you have rd is aliased to PortA.4?

    Out of curiosity, I don't see you're actually reading the data that the card outputs. Are you "playing" it directly to a DAC or something like that?

    /Henrik.

  3. #3
    Join Date
    Jul 2015
    Posts
    7


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Henrik, thanks for your reply.
    Yes, I am getting all of the 16bit data out of the CF card. With the REPEAT....UNTIL after each block data call (4x256)
    and with the GOSUB dat....RETURN used only once as a GOSUB. It isn't a timing issue with the CF card, it's that
    the pulse counting "until i = 65535" seems to not work after running the program 5 times when using the GOSUB...RETURN.
    Yes, I'm playing to a DAC.

    The REPEAT...UNTIL is from the PBP manual and I adjusted it to work with my output pin. I'm new at this, so getting
    it to work in the first place is a big deal.

    The way I understand the sample from the manual:
    i = 0 zeros out the word variable count
    REPEAT
    RD[i] = 1 aliasies the RD pin (PORTC.1 pin) to i and sets this pin HIGH to start.
    i = i + 1 adds the count to word variable i
    PULSOUT RD, 4 pulses the RD pin low
    UNTIL i = 65535 keeps pulsing low until i variable reaches a count of 65535

    This works except for the fifth time when used with the GOSUB....RETURN.
    It's like the UNTIL i = 65535 hasn't counted up and stopped the pulsing.

    Thanks.

  4. #4
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,516


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Hi,
    You're missing my point - I think.
    You have the variable rd aliases to PortA.3 (not PortC.1 as far as I can see) but what is supposed to happen inside the loop when you acces the rd "variable" as if it was an array - which is what you're doing with the rd[i] thing.

    i will increment once per iteration. Each iteration thru the loop you do RD[i] = 1 where, as we said, i increments by one each time. What happens when i is, for example 1234, and the effect of the line is PortA.3[1234] = 1?

    I don't think the problem has anything to do with the use of GOSUB or REPEAT UNTIL, I think it's just a coincidence and the fact that it works with the code pasted in multiple places just masks the real issue - which I think is the RD[i] = 1 line.

    If what you want is to ensure that the RD-line is high before starting the pulsing I'd try
    Code:
    dat:
       i = 0           'pulse RD low 65535 times
    RD = 1     '<---No indexing stuff, just set the pin high.
    REPEAT
       i = i + 1
       pulsout rd, 4   '44.1KHz Playback
    UNTIL i = 65535
    RETURN
    /Henrik.

  5. #5
    Join Date
    Jul 2015
    Posts
    7


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Henrick,

    Yes, sorry, RD is variable of pin PORTA.3
    The "RD[i] = 1" is from the PBP manual where I subbed RD for a PORTx.x pin in the original.
    I'll try your suggested change.
    Thanks,
    Jim

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,516


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Hi,
    RD is just a name that you created which points to same memory adress (PortA) and bit at that adress (.3) as PortA.3 does.

    So RD[i] is then the same thing as PortA.3[i] but why are you doing it? What's the intended purpose of the [i] part of it?

    What will happen is that the first time thru the loop (when i=0) you will set PortA.3 high - which I think is all you want to do, but please correct me if that's not the case. Next time (when i=1) you'll set PortA.4 high. Next time (when i=2) you'll set PortA.5 high and so on. When i is 23456 you will set a bit, which 23456 bits "away" from PortA.3 in the memory map....

    Look at sextion 7.6.5 in the PBP3 manual for more details on array indexing, which is what you're doing effectively.

    I think you'll see the potential issue with this and the fact that it worked before is just pure luck as far as I can see.

    /Henrik.
    Last edited by HenrikOlsson; - 28th July 2015 at 21:07.

  7. #7
    Join Date
    Jul 2015
    Posts
    7


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Henrick,

    I tried your suggestion and it still vapour locks after the fifth "play" start button push.

    This is from the PBPro manual:

    i = 0 They don't tell you "i" needs to be a variable, I figured it out after awhile though.
    REPEAT
    PORTB.0[i] = 0 I changed the PORTB.0 to my RD variable name for my PORTA.3 pin and made the pin = 1 to start high
    i = i + 1 I added the PULSOUT RD, 4 so that the pin would pulse LOW
    UNTIL i > 7 I changed the ">" to "=" so that when i = 65535 it was done

    It was the only example I could find where I could pulse a pin for a certain number of times.

    All I'm doing is pulsing the RD pin low 65535 times. Each time the pin is pulsed low the i variable counts up
    and when the count reaches 65535, it stops pulsing and continues on with what was next in the code.

    I'm trying to use the GOSUB...RETURN so that I'm not using up space having 4 separate REPEAT....UNTIL's in the code.

    I'm not trying to do any "array indexing".

    Thanks, Jim

  8. #8
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,516


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Hi Jim,
    It was the only example I could find where I could pulse a pin for a certain number of times.
    That's not what that particullar code example does. It IS "indexing" port pins starting at PortB.0 and ending at PortB.7 setting them low, one by one.

    I'm not trying to do any "array indexing".
    I figured you're not trying to but that IS effectively what you're doing ;-)

    PortA.3 = 1 will set PortA.3 high - this is what you want.
    PortA.3[3]=1 will set PortA.6 high because you're adding an offset of 3 - not what you want in this case.
    PortA.3[i] will set "something" high - what that "something" is depends on the value of i which is incrementing each time thru the loop - definitely not what you want in this case.

    All I'm doing is pulsing the RD pin low 65535 times. Each time the pin is pulsed low the i variable counts up and when the count reaches 65535, it stops pulsing and continues on with what was next in the code.
    Yes and no. You're actually pulsing the pin 65536 times, since you're starting at 0 and stopping at 65535 but I Think 65536 is what you want. And since the i variable is couting up you're setting 65536 consecuitive bits, starting at PortA.3 high.

    As a test, try
    Code:
    dat:
    RD = 1
    For i = 0 to 65535
       RD = 0      ' Pull pin low
       PAUSEUS 10    ' Wait 10us
       RD = 1    ' Pull pin high
       PAUSEUS 10    ' Wait 10us
    NEXT
    RETURN
    /Henrik.

  9. #9
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,516


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Oh, one more thing....which I should have caught from the start:
    Before the dat subroutine you need to put a GOTO Mainloop, otherwise the execution will "fall into" the dat subroutine after the last GOSUB dat you have in there. When it then hits the RETURN there's no matching GOSUB and you'll have a stack underflow and it goes off to la-la-land. I suspect THAT is what you're seeing but the issues with unintentional "array indexing" is still very much relevant!

    /Henrik.

  10. #10
    Join Date
    Jul 2015
    Posts
    7


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Henrick,

    I see what you mean, I took the wrong example for what I wanted, messed with it and by pure luck
    it worked if I used it where/when I needed it and not used in a GOSUB!

    I tried your code example and it worked for five "start" button presses and then the same problem
    where the RD pin doesn't stop pulsing at 65535 and just keeps running on.

    Thanks for your time and help,

    Jim

  11. #11
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,516


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Hi Jim,

    Did you add a GOTO Mainloop at the end of the actual Mainloop, before the subroutine?
    If so, can you post the code again, exactly as it is now? We'll get it sorted and ironed out.
    I have to sign off for today though.

    /Henrik.

  12. #12
    Join Date
    Jul 2015
    Posts
    7


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Henrick,

    Just saw your last post about the GOTO MAINLOOP
    You're saying to put it above the dat: subroutine and not below it like I
    have it now. I'll try it out.
    Thanks,
    Jim

  13. #13
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,516


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Hi Jim,

    Yes, before the dat subroutine.

    If there is no Goto Mainloop there the program will "fall into" the subroutine as it comes out of the main loop. Since it wasn't intentionally jumped to with a GOSUB at that time it doesn't know where to go once it gets to the RETURN at the end of the subroutine and it all falls to pieces.

    Look at this:
    Code:
    Mainloop:
      Do this
      Gosub Sub_1
      Do something else
      Gosub Sub_2
    Goto MainLoop
    
    Sub_1:
      Whatever
    RETURN
    
    Sub_2:
      Whatever
    RETURN
    If the Goto MainLoop isn't there the program will just continue into Sub_1 as if it was actually called with a GOSUB (which it wasn't). So at the end of Sub_1 there's a RETURN but to where should it return? There's no return adress on the stack. Things go bad.

    Hope that makes sense. Midnight here, got to go now.

    /Henrik.

  14. #14
    Join Date
    Jul 2015
    Posts
    7


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Henrik,

    That was it! I had my GOTO Mainloop after the dat: subroutine. I moved it up like you
    mentioned and it works.

    GOSUB dat 'last gosub dat

    GOTO MAINLOOP
    dat:
    RD = 1
    For i = 0 to 65535
    RD = 0 ' Pull pin low
    PAUSEUS 10 ' Wait 10us
    RD = 1 ' Pull pin high
    PAUSEUS 10 ' Wait 10us
    NEXT
    RETURN

    END

    Thanks a ton! If you were here, I'd buy you a beer.
    Instead, I'm taking a vacation day tomorrow and goin' fishing.

    Jim

  15. #15
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Quote Originally Posted by HEXhacker View Post
    Henrik,



    Thanks a ton! If you were here, I'd buy you a beer.
    Instead, I'm taking a vacation day tomorrow and goin' fishing.

    Jim
    Wow, beer and fishing all in the same post
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  16. #16
    Join Date
    Oct 2014
    Location
    Lagos Nigeria
    Posts
    10


    Did you find this post helpful? Yes | No

    Thumbs up Re: Help with GOSUB

    One thing i have learnt about pbp;

    NEVER use GOSUB without a matching RETURN;
    NEVER use RETURN without a matching GOSUB

    but when using ASM, i seem to get away with using goto with return and sometimes i can call a sub that terminates with a goto... don't know why it worked but then maybe pbp GOSUB is very much different from asm CALL

    stanon1

  17. #17
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,516


    Did you find this post helpful? Yes | No

    Default Re: Help with GOSUB

    Whenever you GOSUB somewhere the adress after from where you GOUSBed is pushed onto the stack (stored in memory). If another GOSUB is executed the adress after THAT gosub is pushed onto the stack and the first adress stored is "pushed down". When a RETURN is executed the adress at the top of the stack is popped (retreived) and the execution jumps to that adress. This is how it works in any language, not just PBP.

    If you GOSUB somewhere you must go back with a RETURN.
    You can not RETURN from somwhere to where you did not GOSUB.

    This too is NOT unique to PBP.

    Now, it's perfectly fine to use GOTO from a subroutine to which you jumped with a GOSUB as long as you eventually end up at a "matching" RETURN. Example:
    Code:
    Main:
    Toggle PortB.0
    Pause 100
    GOSUB CheckSwitch
    Goto Main
    
    CheckSwitch:
    If PortA.0 = 1 THEN
    GOTO DoThis
    ELSE
    GOTO DoThat
    ENDIF
    RETURN
    
    DoThis:
    ' Whatever
    RETURN
    
    DoThat:
    ' Whatever
    RETURN
    In the above example the RETURN instryction at the end of DoThis and DoThat "matches" the GOSUB in the Main loop, Everything is fine. However, if you in somewhere in the main loop (or whatever) did a GOTO DoThat things would go bad because there's a "non matching" RETURN at the end. When the execution hits that RETURN it will pop "something" of off the stack and go there - not what you want.

    Again, this is NOT unique to PBP in any way.

    /Henrik.

Similar Threads

  1. gosub - return
    By l_gaminde in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 11th August 2010, 11:21
  2. On...gosub
    By circuitpro in forum PBP Wish List
    Replies: 5
    Last Post: - 7th December 2009, 22:40
  3. If ... Then Gosub <> If ... Then Goto?
    By oldtoddler in forum General
    Replies: 6
    Last Post: - 27th February 2006, 12:52
  4. gosub and if-then working together?
    By bartman in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 23rd November 2005, 14:54
  5. GoSub Problem
    By ghoot in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 11th May 2004, 16:15

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts