PDA

View Full Version : Reassigning I/O within the program ?



Del Tapparo
- 6th June 2010, 00:04
I would like to reassign I/O pins to specific variables based on the state of an input pin. Can I do this? e.g.

If Input = 1 then
Variable1 = PORTB.1
else
Variable1 = PORTB.2
endif

But the above doesn't work. Is there another way? I would like to do this at the beginning of the program, just once.

Darrel Taylor
- 6th June 2010, 00:29
You could use PIN numbers instead of PORT.bit.




InputSelect VAR PORTB.0
myPIN VAR BYTE

Test:
IF InputSelect = 1 THEN
myPIN = 1 ; PORTB.1 selected
ELSE
myPIN = 2 ; PORTB.2 selected
ENDIF

HIGH myPIN
PAUSE 500
LOW myPIN
PAUSE 500
GOTO Test


Or, a similar version.
The Inputselect will always read 0 or 1. Add 1 to it to make 1 or 2, for PORTB.1 and PORTB.2.


InputSelect VAR PORTB.0
myPIN VAR BYTE

Test:
myPIN = InputSelect + 1

HIGH myPIN
PAUSE 500
LOW myPIN
PAUSE 500
GOTO Test

The ports used depends on the chip you are using.
Check the .bas file for the PIC you are using in the PBP folder. (ex. 16F877a.bas)

PORTL and TRISL determine which PORT that pin numbers 0-7 go to.
PORTH and TRISH determine which PORT that pin numbers 8-15 go to.
<br><br>

Del Tapparo
- 6th June 2010, 00:42
Yes, there are many ways to achieve this within the loop of the main program. I was trying avoid having to make pin decisions every time I wanted to collect data. I just want to reassign the pins at the beginning of the program, and never worry about it again (i.e. less code).

Having thought about this for awhile now, I think the easiest way is to just make a subroutine for each data input (e.g. Get_Data) that makes the I/O pin decision each time I need the data. It still gobbles up a bunch of code, but is still relatively easy to follow the logic.

Darrel Taylor
- 6th June 2010, 00:46
Yes, there are many ways to achieve this within the loop of the main program. I was trying avoid having to make pin decisions every time I wanted to collect data. I just want to reassign the pins at the beginning of the program, and never worry about it again (i.e. less code).
I don't see a difference there.

If you set the PIN variable at the top of the program instead of in the main loop, it's the same thing.

Best regards,

Del Tapparo
- 6th June 2010, 01:52
I get it now ....

In my case, all of the reassigned inputs use the PULSIN command. I simply assign a variable to the pin portion of the PULSIN command, separate from the resulting input data variable.

Thanks Darrel! Much appreciated.

tenaja
- 6th June 2010, 13:22
I don't like needing to check the compiler files for information, because changing PICs can be a hassle, especially when you forget about it.

When I did it (years ago) I had to do something like this...
myPIN = 2 ...set this in your IF statements
low portb.0[myPIN] ...allows you to use any port you like, and changing PICs is easy.

Darrel Taylor
- 6th June 2010, 19:15
>myPIN = 2 ...set this in your IF statements
>low portb.0[myPIN]

That would READ PORTB.2, and set either PORTB.0 or PORTB.1 low depending on the state of RB2(0 or 1).

portb.0[myPIN] = 1 ; lets you control any pin, assuming TRIS has been set

But it can't be used in SERIN/OUT, PULSIN/OUT, RCTIME, HIGH/LOW, etc., like the PIN numbers can.

tenaja
- 6th June 2010, 23:45
>myPIN = 2 ...set this in your IF statements
>low portb.0[myPIN]

That would READ PORTB.2, ....
How in the world wout that READ a pin?

Darrel Taylor
- 7th June 2010, 01:05
How in the world wout that READ a pin?

With most PBP statements, you only have 3 options for the PIN's.
It's usually described like this in the manual ...

Pin may be a constant, 0-15, or a variable that contains a number 0-15 (e.g. B0) or a pin name (e.g. PORTA.0).

But portb.0[myPIN] is an Array operation.
The only one of the 3 options that fits an array result is "or a variable that contains a number 0-15".

In order to know which PIN to use, it has to READ the variable, or in this case do the array operation (reading a PIN).
Since it's a BIT array, it will only see a 1 or a 0.

hth,

tenaja
- 7th June 2010, 18:03
With most PBP statements, you only have 3 options for the PIN's.
It's usually described like this in the manual ...


But portb.0[myPIN] is an Array operation.
The only one of the 3 options that fits an array result is "or a variable that contains a number 0-15".

In order to know which PIN to use, it has to READ the variable, or in this case do the array operation (reading a PIN).
Since it's a BIT array, it will only see a 1 or a 0.

hth,

Either we are miscommunicating, or they have changed the way bit arrays work, or you must be misunderstanding bit arrays. I have been using this method for 8 years:
PORTB.0[PinToChange] = NewPinState

The value for PinToChange can be any number 0 to7, and this allows you to use it on ANY PORT. The value for NewPinState must be 0 or 1.

PORTA.0[4] = NewPinState
PORTB.0[4] = NewPinState

Will set PortA.4 AND PortB.4 to the NewPinState

Darrel Taylor
- 7th June 2010, 18:18
Either we are miscommunicating, or they have changed the way bit arrays work, or you must be misunderstanding bit arrays. I have been using this method for 8 years:
PORTB.0[PinToChange] = NewPinState

Obviously miscommunicating.

In post #6 you originally said

myPIN = 2 ...set this in your IF statements
low portb.0[myPIN] ...allows you to use any port you like, and changing PICs is easy.


In my reply I stated that portb.0[myPIN] = 1 will work, but it can't be used as a PIN in PBP statements like SERIN/OUT, PULSIN/OUT, RCTIME, HIGH/LOW, etc.

LOW is a PBP statement with a PIN parameter.

tenaja
- 7th June 2010, 23:46
Oops, well, I meant them to match. :eek:
The second was pasted from a working file. I don't know why the syntax wouldn't work for a LOW, though.

The point is, though, that there are ways to do it without the IFs. On the other hand, PBP is dreadfully inefficient, so it might be better to use the IFs anyway.

Darrel Taylor
- 8th June 2010, 00:02
... I don't know why the syntax wouldn't work for a LOW, though.
That's what I was trying to explain in post#9.
If there's something in that post you don't understand, I'll try to go a little deeper.


The point is, though, that there are ways to do it without the IFs. On the other hand, PBP is dreadfully inefficient, so it might be better to use the IFs anyway.
I completely disgree.
There are many ways to be inefficient with PBP, but PBP itself is not the bottleneck.

mackrackit
- 8th June 2010, 00:29
Originally Posted by tenaja
... I don't know why the syntax wouldn't work for a LOW, though.
LOW sets the TRIS and an array can not be TRISed.


PBP is dreadfully inefficient,
For what it is worth I also disagree. That almost sounds like the poster that says "I know my code is good so it has to be something else". 99% of the time the problem is the person on the keyboard. If you understand PBP and the understand the chip you are using PBP is very efficient.

tenaja
- 8th June 2010, 01:09
Ah, yes, I'd forgotten about the tris part.


For what it is worth I also disagree. That almost sounds like the poster that says "I know my code is good so it has to be something else". 99% of the time the problem is the person on the keyboard. If you understand PBP and the understand the chip you are using PBP is very efficient.

Regarding your (plural) responses here, then we will respectfully disagree. For there to be "efficient" code, there must be something "inefficient" to compare it to. If you were to compare it to asm, then PBP is horrendous--as most compilers are, if the asm author knows his head from a hole in the ground. So that point is moot. However, if you compare it to a similar compiler, say, Proton, then PBP still only gets a "B" grade, which in my opinion is inefficient. In almost every instance I have compared, PBP is a minimum of 10% less efficient than Proton. In some instances, I've saved noticeably more.

The task in this simple topic here shows it:

PBP:

PinToChange Var Byte
NewPinState Var bit

pintochange = 4
newpinstate = 1

PORTB.0[PinToChange] = NewPinState
pintochange = 2
newpinstate = 0
PORTB.0[PinToChange] = NewPinState

low PORTB.0
end '74 words used

Proton:

PinToChange Var Byte
NewPinState Var Bit

pintochange = 4
newpinstate = 1
LoadBit PORTB, PinToChange, NewPinState

pintochange = 2
newpinstate = 0
LoadBit PORTB, PinToChange, NewPinState

Low PORTB.0
End '67 words used

Just on this simplest of examples, PBP takes up more than 10% extra code space.

On top of that, I can actually EASILY see the generated asm code, and see where inefficiencies take place:

PROTON#CODE#START
ORG 0
GOTO PROTON#MAIN#START
A@BIT
MOVWF 13
ANDLW 248
MOVWF 12
RRF 12,F
RRF 12,F
RRF 12,W
ADDWF 4,F
CALL C@BT
MOVWF 13
ANDWF 0,W
GOTO I@NT
C2@FB
MOVF 13,W
SKPC
CLRW
XORWF 0,W
ANDWF 13,W
XORWF 0,F
GOTO I@NT
C@BT
MOVLW (C@TBL >> 8)
MOVWF 10
MOVF 13,W
ANDLW 7
ADDWF 2,F
C@TBL
RETLW 1
RETLW 2
RETLW 4
RETLW 8
RETLW 16
RETLW 32
RETLW 64
RETLW 128
I@NT
BCF 3,7
I@NT2
BCF 3,5
BCF 3,6
RETURN
PROTON#MAIN#START
F2_SOF EQU $ ; TEST.PRP
F2_EOF EQU $ ; TEST.PRP
F1_SOF EQU $ ; TEST.BAS
F1_000012 EQU $ ; IN [TEST.BAS] PINTOCHANGE VAR BYTE
F1_000013 EQU $ ; IN [TEST.BAS] NEWPINSTATE VAR BIT
F1_000015 EQU $ ; IN [TEST.BAS] PINTOCHANGE = 4
MOVLW 4
MOVWF PINTOCHANGE
F1_000016 EQU $ ; IN [TEST.BAS] NEWPINSTATE = 1
BSF _B#VR1,0
F1_000017 EQU $ ; IN [TEST.BAS] LOADBIT PORTB, PINTOCHANGE, NEWPINSTATE
MOVLW PORTB
MOVWF FSR
MOVF PINTOCHANGE,W
ADDLW 0
CALL A@BIT
BCF STATUS,0
BTFSC _B#VR1,0
BSF STATUS,0
CALL C2@FB
F1_000019 EQU $ ; IN [TEST.BAS] PINTOCHANGE = 2
MOVLW 2
MOVWF PINTOCHANGE
F1_000020 EQU $ ; IN [TEST.BAS] NEWPINSTATE = 0
BCF _B#VR1,0
F1_000021 EQU $ ; IN [TEST.BAS] LOADBIT PORTB, PINTOCHANGE, NEWPINSTATE
MOVLW PORTB
MOVWF FSR
MOVF PINTOCHANGE,W
ADDLW 0
CALL A@BIT
BCF STATUS,0
BTFSC _B#VR1,0
BSF STATUS,0
CALL C2@FB
F1_000023 EQU $ ; IN [TEST.BAS] LOW PORTB.0
BSF STATUS,5
RAM_BANK = 1
BCF TRISB,0
BCF STATUS,5
RAM_BANK = 0
BCF PORTB,0
F1_000024 EQU $ ; IN [TEST.BAS] END
PB@LB2
SLEEP
GOTO PB@LB2
F1_EOF EQU $ ; TEST.BAS
PB@LB3
GOTO PB@LB3

If I find a bottleneck that I need to speed up, I can count the words right there. If I want, I can recode it in basic, or copy/paste the asm and edit with my own optimizations.

See, my comments were directly related to the efficiency of the COMPILER. They had nothing to do with your coding or your abilities.

mackrackit
- 8th June 2010, 01:27
Then why do you even bother with PBP? Just stick with Proton.

Darrel Taylor
- 8th June 2010, 01:50
On top of that, I can actually EASILY see the generated asm code, and see where inefficiencies take place:

For the beniefit of those of us that don't use PROTON....
And since you only gave the ASM generated by PROTON...

Could you please explain the difference.
Relative to PINS and ARRAY's. And the ASM generated by PBP?

tenaja
- 8th June 2010, 03:10
Then why do you even bother with PBP? Just stick with Proton.
For the most part, I do. But I have PBP, and it's very similar to PDS in syntax (based on BS2), so I hang out here to learn and share.


For the beniefit of those of us that don't use PROTON....
And since you only gave the ASM generated by PROTON...

Could you please explain the difference.
Relative to PINS and ARRAY's. And the ASM generated by PBP?
ASM code for PBP?

MOVE?CB 0C0h, ADCON0
MOVE?CB 004h, _PinToChange
MOVE?CT 001h, _NewPinState
AIN?TTB _NewPinState, _PORTB??0, _PinToChange
MOVE?CB 002h, _PinToChange
MOVE?CT 000h, _NewPinState
AIN?TTB _NewPinState, _PORTB??0, _PinToChange
LOW?T _PORTB??0
END?
Hardly indicative of the amount of code space used...
You actually have to use the LST file. I'll post it later...