I have a subroutine that turns a port pin on or off based on a numerical index:
SubTurnOnOff(index,level)' level is ON or OFF Select Case i Case 1 SetWith( portA.2, level) Case 2 SetWith( portA.5, level) Case 3 SetWith( portC.0, level) Case 4 SetWith( portC.3, level) Case 5 SetWith( portC.6, level) Case 6 SetWith( portB.0, level) Case 7 SetWith( portB.3, level) Case 8 SetWith( portB.3, level) End SelectEnd Sub
It would seem like using an array would be a natural way to handle this, but the following doesn't work:
device_ports = portA.2, portA.5, portC.0, portC.3, portC.6, portB.0, portB.3, portB.3
Sub TurnOnOff(index, level)
' level is ON or OFF
SetWith(device_ports(index), level)
End Sub
Is there another way this could be done? I'm using Version: 0.98.02 2018-05-16 (Linux), FWIW.
-Jim
Last edit: Jim Gregory 2018-10-16
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ports are not Variables, they are Physical registers within the target device, therefore, you cannot form an array of Ports.
So the short answer is that you can not do what you want to do.
Now for the Long answer............
If you look at the Datasheet for the PIC16 family some interesting patterns emerge that may help:
Each Port is actually an Array of Bits that we normally address in the form of PortX.BitX for example PortB.4 is device Pin RB4
The Port Registers are 8 bit and consecutively maped in the Memory Space of the Device.
So if you are ready we can delve into The Dark Art of Bit Manipulation to find a possible solution.
Disclaimer:
What follows is not a good technique in the wrong hands. This sort of coding should only be used with care and a full understanding of the Device Memory Map and all of its Registers. In addition you can forget about Portability if you use Direct Address Level access to the Device.
Your mileage may vary, batteries not included.
That said, it should port across most PIC16 devices.
Now let's get down to the fun......
GCBASIC has a useful function that allows us to determine the address of a object, for example:
It also has PEEK and POKE Commands that allow access to anywhere in the Memory Map.
So from point 2. above we can use @PortA to infer the address of all of the I/O Ports of the device then use Peek and Poke to access them.
So rather than creating an Array we will use the existing memory map as if it were an Array.
The first thing we need to determine is how to Index the Array, keeping in mind that it is an array of bits. Having obtained a base point we can take it as the Base of the Array and we need our own function to access it.
Effectively it is a two dimensional Array composed of (Port, Bit) and could be addressed as:
Sub TurnOnOff(MyPort, MyBit, Level)
But your initial request was to access tha array in the form of:
Sub TurnOnOff(index, level)
So I will treat it as such. I think the Best solution is to treat PortA as zero, so Porta.0 or in RA0 would be index 0x00 and RA7 would be Index 0x07. We could then say that PortB was indexed as 0x10 for RB0 and 0x17 for RB7.
Notice that I am indexing in Hexadecimal. This is essential when working at register or Direct memory access level as all registers and memory locations are addressed in Hex and are 8 or 16 bit wide. In this instance Octal would be the better choice but as far as I am aware GCBASIC has no Octal Numerical Type.
The Solution:
This is what i came up with for the fist pass:
SubTurnOnOff(inIndexasword,inLevel)' Index is the Port/Bit Number (PortA.4 = 0x04, PortB.1 = 0x11 etc.) 'levelisONorOFFDimBitXasByteBitX=IndexAND0x0FIndex=FnLSR(Index,4)Index+=@PORTAifLevelthenPokeIndex,Peek(Index)ORFnLSL(1,BitX)elsePokeIndex,Peek(Index)ANDNOTFnLSL(1,BitX)EndifEndSub
Expanding that into quick example Program to Flash an LED would now be:
;Chip Settings#chip16f628aDirPortBOutDimMyIndexasByteMyIndex=0x14' PortB Bit 4 ie RB4 Do Forever TurnOnOff(MyIndex, ON) Wait 250 ms TurnOnOff(MyIndex, OFF) Wait 250 ms Loopend
Taking the Example one step further we can bring it closer to your original request by defining an Array of Hexadecimal values to suit your intended ports and use that as an index into the TurnOnOff() subroutine.
I am also using slightly more obscure names for the final code as names like Index are common and could cause conflicts in a function/sub that may be used by others.
As I don't have access to your hardware and I do not know your intended application, I used a 16F877a in Real PIC Simulator to create a chase sequence on 8 LED's as per your example ports:
Not animated unfortunately but you get the idea :)
I have a subroutine that turns a port pin on or off based on a numerical index:
It would seem like using an array would be a natural way to handle this, but the following doesn't work:
Is there another way this could be done? I'm using Version: 0.98.02 2018-05-16 (Linux), FWIW.
-Jim
Last edit: Jim Gregory 2018-10-16
Ports are not Variables, they are Physical registers within the target device, therefore, you cannot form an array of Ports.
So the short answer is that you can not do what you want to do.
Now for the Long answer............
If you look at the Datasheet for the PIC16 family some interesting patterns emerge that may help:
Each Port is actually an Array of Bits that we normally address in the form of PortX.BitX for example PortB.4 is device Pin RB4
The Port Registers are 8 bit and consecutively maped in the Memory Space of the Device.
So if you are ready we can delve into The Dark Art of Bit Manipulation to find a possible solution.
Disclaimer:
What follows is not a good technique in the wrong hands. This sort of coding should only be used with care and a full understanding of the Device Memory Map and all of its Registers. In addition you can forget about Portability if you use Direct Address Level access to the Device.
Your mileage may vary, batteries not included.
That said, it should port across most PIC16 devices.
Now let's get down to the fun......
GCBASIC has a useful function that allows us to determine the address of a object, for example:
It also has PEEK and POKE Commands that allow access to anywhere in the Memory Map.
So from point 2. above we can use @PortA to infer the address of all of the I/O Ports of the device then use Peek and Poke to access them.
So rather than creating an Array we will use the existing memory map as if it were an Array.
The first thing we need to determine is how to Index the Array, keeping in mind that it is an array of bits. Having obtained a base point we can take it as the Base of the Array and we need our own function to access it.
Effectively it is a two dimensional Array composed of (Port, Bit) and could be addressed as:
But your initial request was to access tha array in the form of:
So I will treat it as such. I think the Best solution is to treat PortA as zero, so Porta.0 or in RA0 would be index 0x00 and RA7 would be Index 0x07. We could then say that PortB was indexed as 0x10 for RB0 and 0x17 for RB7.
Notice that I am indexing in Hexadecimal. This is essential when working at register or Direct memory access level as all registers and memory locations are addressed in Hex and are 8 or 16 bit wide. In this instance Octal would be the better choice but as far as I am aware GCBASIC has no Octal Numerical Type.
The Solution:
This is what i came up with for the fist pass:
Expanding that into quick example Program to Flash an LED would now be:
Taking the Example one step further we can bring it closer to your original request by defining an Array of Hexadecimal values to suit your intended ports and use that as an index into the TurnOnOff() subroutine.
I am also using slightly more obscure names for the final code as names like Index are common and could cause conflicts in a function/sub that may be used by others.
As I don't have access to your hardware and I do not know your intended application, I used a 16F877a in Real PIC Simulator to create a chase sequence on 8 LED's as per your example ports:
Not animated unfortunately but you get the idea :)
I hope that helps.
Cheers
Chris
Last edit: Chris Roper 2018-10-16
I'm not sure what the original request was about but your solution reminds me of picaxe basic.