Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Need Help With Converting Subroutines to Macro

Status
Not open for further replies.

EvilGenius

Member
Language: Assembly
Microcontroller: PIC16F628A
Hello
I need help consolidating several subroutines into a macro.
Here is the simplified setup:
I have main subroutines: Main1, Main2, Main3
Function of Main1-3 are identical.
Main1 calls two subroutines SubA and SubB (with a return).
Main2 calls two subroutines SubC and SubD (with a return).
Main3 calls two subroutines SubE and SubF (with a return).
-------------------------------------------
Now I would like to convert "Main" into a macro and set it up once.
Then be able to do the macro such that I can substitute different subroutine labels in it.
Example:
------------------
Macro Main SubX, SubY
Place label SubX into SubK
Place label SubY into SubJ
Do Something involving calling SubK and then SubJ
endm
------------------
Main SubA,SubB
Main SubC,SubD
Main SubE,SubF
-------------------
How do I do this?

Thank you in advance for your assistance.
Regards,
Rom
 
I think what you're trying to do is create a single macro that you can pass arguments to. Can you post up your subroutines so that we can see exactly what you're trying to do?

Furthermore...keep in mind that the macro code is inserted as inline code each time the macro is invoked. It may make more sense to keep them as a subroutine instead to make your code tighter, depending on how you're implementing this. But I can further advise you once I see the code that you're working with.
 
I think what you're trying to do is create a single macro that you can pass arguments to
Hi Jon, That is correct. I will try to post some codes but I am afraid once I do that, we get distracted by how the subroutines work and get off the topic.
I am trying to save program space and keep it clean by switching to a macro. Otherwise I will have several main routine (which are lengthy) with each having two mini subroutine calls in them which takes up valuable space. I rather have one main subroutine and be able to switch sets of mini subroutines in it via macro.
I have not tried this but worth mentioning it if you think it might work: what if I put the labels in a "Quotation" as the means of substitution in the main routine?

Regards
Rom
 
Last edited:
Here you see the main subroutine called "Morph" which calls on two smaller subroutines within it (Frame1, Frame2). This example only shows 2 mini subroutines. My code uses Frame1, 2, 3, 4, 5, 6 which are paired. Instead of writing Morph1 call Frame1, call Frame2 within it. Then call Morph2, call Frame3, Frame4 within it. And so on. I like to have one Macro "Morph" and macro call and substitute Frame1, Frame2 once. Then Frame3, Frame4 and so on. I hope this helps. FYI, as you can see "Display" is a macro within "Frame".


Code:
Morph
        movfw     Speed2
        movwf     Loop
M0
        call           Frame2
        decfsz      Loop
        goto         M0
;
        movfw    Speed        ; controls speed of rotattion
        movwf    LoopCount
M1
        movfw    LoopCount
        movwf    Trans1
        sublw      Speed+1    ;this is always plus 1
        movwf    Trans2
M2
        call          Frame1
        decfsz     Trans2,F
        goto        M2
M3
        call          Frame2
        decfsz     Trans1,F                             
        goto         M3
        decfsz     LoopCount
        goto        M1
        return
;----------------------------------------------------
Frame1
         Display C12,b'110000000000'
         Display C11,b'011000000000'
         Display C10,b'001100000000'
         Display C9,b'000110000000'
         Display C8,b'000011000000'
         Display C7,b'000001100000'
         Display C6,b'000000110000'
         Display C5,b'000000011000'
         Display C4,b'000000001100'
         Display C3,b'000000000110'
         Display C2,b'000000000011'
         Display C1,b'100000000001'
         return
;----------------------------------------------------
Frame2
         Display C24,b'110000000000'
         Display C23,b'011000000000'
         Display C22,b'001100000000'
         Display C21,b'000110000000'
         Display C20,b'000011000000'
         Display C19,b'000001100000'
         Display C18,b'000000110000'
         Display C17,b'000000011000'
         Display C16,b'000000001100'
         Display C15,b'000000000110'
         Display C14,b'000000000011'
         Display C13,b'100000000001'
         return
;----------------------------------------------------
 
Last edited:
The ultimate question is this: We know we can pass a value (or values) to a variable (or multiple variables) via a macro. Can an argument(label) be passed on via a macro as well? If yes, how is that implemented differently?
 
What exactly is "Display Cx"? Is this some macro that you've created? If so, I will need to see the macro code as well.

Macros vs Subroutines -

A macro is just a shorthand alias that tells the assembler to "insert this block of inline code (and include these arguments) every time you see me". So each time you invoke a macro, the assembler will insert a block of code repeatedly.

A subroutine is a block of code that will only be assembled in once, and a "call" to this subroutine will just jump the program counter to that block of code while a "return" instruction at the end of the code block will return the PC to the instruction following the call instruction which called it. With this method, the subroutine code block will only be in one location in code rather than inserted inline every time like a macro would be. This saves valuable space.

Now we can integrate subroutines and macros by canning a block of code as a subroutine, then creating a macro which passes arguments to this subroutine. This way the macro is inserting ever changing inline code while the subroutine is the code block that remains the same every time.

Make sense?
 
Last edited:
Now we can integrate subroutines and macros by canning a block of code as a subroutine, then creating a macro which passes arguments to this subroutine. This way the macro is inserting ever changing inline code while the subroutine is the code block that remains the same every time.

Make sense?
I am not sure what you are trying to say regarding your text above. I know the difference between macro and subroutine.
I am trying to avoid multiple subroutines for "Morph" by turning it into a macro and invoking it multiple times with two different sets of "Frames" each time and do this multiple times throughout the program.

Cx is 4 bit (binary) color bit that gets added to 12-bit (binary data bits) before they are divided into two groups of 8 bits to be split into PORTA and PORTB.
I think you are missing the point of the question. I am not trying to pass a value (number) via an argument thru the macro. I am trying to pass a label thru the argument. This may not be possible due to inherent characteristic of the macro. While Morph remains the same and does a pseudo PWM between two Frames (subroutines), I like to be able to change the actual name of the Frames from Frame1+Frame2 to Frame3+Frame4. Frame is not a number, it is just the name of the subroutine that is called from Morph. See above posted code.

You have everything you need to have in the code above. It does not matter if it calls on other subroutines or invokes other macros within the macro/subroutine. But you needed to know as the subroutine Morph is not just toggling between numbers but rather toggling between two subroutines. I hope this makes sense and you can shed some light on what a macro can or cannot do in regards to what I am trying to do with it.
 
I think I have your solution.

Designate a software flag bit in a GPR register and either set or clear (depending on whether you want to call Frame1/Frame2 or Frame3/Frame4) this flag prior to calling Morph. This flag will be read in Morph to tell Morph whether to call Frame1 and Frame2 or Frame3 and Frame4. Here is the code I came up with -

Code:
FRAME34	EQU	0X70,0		;place this with all other register/bit aliases

Morph:
	movfw	Speed2
	movwf	Loop

M0:
	call	Frame24
	decfsz	Loop		;decrement loop counter
	goto	M0		;loop if counter > 0
	movfw	Speed		;counter = 0
	movwf	LoopCount
M1:
	movfw	LoopCount
	movwf	Trans1
	sublw	Speed+1		;this is always plus 1
	movwf	Trans2
M2:
	call	Frame13
	decfsz	Trans2,F	;decrement trans counter
	goto	M2		;loop if counter > 0
	
M3:
	call	Frame24
	decfsz	Trans1,F                            
	goto	M3
	decfsz	LoopCount
	goto	M1
	return

Frame24:
	btfsc	FRAME34
	goto	$+3
	call	Frame2
	goto	$+2
	call	Frame4
	return

Frame13:
	btfsc	FRAME34
	goto	$+3
	call	Frame1
	goto	$+2
	call	Frame3
	return

Let me know if this code does what you need it to do.
 
Last edited:
Let me know if this code does what you need it to do.
I am guessing that I assign a value to Frame34 right before a Morph call...
I will try it. This is a good starting point although I need 6 sets of 2-Frames. I need more than 1-bit testing. I also have to account for time delay the testing of frames creates and accordingly adjust Loop and Speed which is not a big deal. Thanks.
Regards,
Rom
 
Last edited:
I am having a wild thought: I don't think this is possible as far as the syntax goes. But what if the Frame calls within Morph is as such:
Call Frame"x"
Call Frame"y"
and assign values 1 thru 6 to x and y!? This way Morph remains the same, and x-y are changed before Morph call?
 
No you don't assign a value to FRAME34. FRAME34 is a single bit, so you either do a "bsf FRAME34" or a "bcf FRAME34" before Morph is called. Morph will call the appropriate Frame subroutine based on whether bit FRAME34 is set or cleared.

If you have more frame subroutines to call you can add to the code as needed. But this should provide a good starting point to give you a basic idea of what needs to happen.
 
Status
Not open for further replies.

Latest threads

Back
Top