if PortPin is a constant. If the constant is a port.pin the will be assigned the bit value of porta.x
If PortPin is a bit variable. It will assigned to bit value of porta.x
If PortPin is a byte variable. It will be assigned 1 or 0 that is the value of porta.x
Compile a program and try. See what happens.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm starting with GCB so my knowledge of its syntax is not that great for the moment.
#chip18F1330,40
#DefineNeoPinPORTB' this is should be a Constant, right?Dim Idx As ByteIdx = 0Do NeoPin.Idx = 1 Wait 500 ms NeoPin.Idx = 0 Wait 500 msLoop
This is my code, not working.
How do I declare a port pin as "variable"? I don't know how to declare it as a bit, btw...
I'm a little confused here.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Your code is highly costly in terms of program memory. Whilst you may not know IDX bit value there are many ways to make this better.
#chip18F1330,40
#DefineNeoPinPORTB' this is should be a Constant, right?Dir NeoPin OutDim Idx As ByteIdx = 0Do NeoPin.Idx = 1 Wait 500 ms NeoPin.Idx = 0 Wait 500 msLoop
You can read the port into a varaible and set the variable.bit and then set the port.
Use a select Case.
Read the port and rotate to set the bit. The hardest to understand, the fastest.
There are other waysm but the above method works but is slow.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks Chris but this is still not what I'm asking for.
So, looking back to my first post, I could have asked otherwise like this:
DimPortPinasByte' this variable is ment to represent a PORTIfaconditionistrueThenLightuptheLEDoni.e.PortPin=PORTA.0ElseLightuptheLEDoni.e.PortPin=PORTC.4EndifSubRoutine:Doneopin=!NeopinWait500msLoop
Is it a little more clear now? Actually, I can't make that work.
Again, to avoid the need of copying tons of code, I have made one subroutine where I then set the needed port.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Now that I have a better understanding of your intent, I can see that you are on totally the wrong track.
All you are doing is assigning a value to a variable called portpin.
What you are attempting to do is assign a value, that is the address of a port, to a variable called portpin and then use that variable to indirectly address a bit within that port.
In short It can't be done in GCBasic in the way that you thought, however, you can work around it in GCBasic by embedding assembler code into your basic code to indirectly address the hardware.
You will lose all portability, and will have to have a good understanding of the Datasheet for the device you are trying to program, but it can be done.
You may also want to try the Help pages and look for Indirect addressing, you may find some answers there which could alleviate the burden of assembly programing.
Cheers
Chris
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This code needs way more clarification before ASM is needed.
~~~
Dim PortPin as Byte ' this variable is ment to represent a PORT
If a condition is true Then
PortPin = PORTA.0
Else
PortPin = PORTC.4
Endif
Sub mySub
Do
neopin=!Neopin
Wait 500 ms
Loop
End Sub
~~~~
What is actually meant to happen?
if some condition is true then the Byte variable is meant to be what? is bit.0 meant to be the state of porta.0 or portc.4 ? or, is variable meant to be 0 or 255? should this be PortPin as a Bit? should this be PortPin.0?
What is happening in the sub? Some other ram register or some other io register is toggling? What has this to with solution as this is an endloop?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I actually opened another thread about #Include/#Insert but it is all for the same project.
So please find here my project and it might help to understand why I'm currently doing the way...it is done. @20MHz, there is a huge timing issue (meaning there is no space at all for GOSUBs, GOTOs et so forth) using the WS2812B NeoPixel strings reason why I have some ultra simple assembler code in it.
My wall clock has four digits made of each a NeoPixel string (4x 28 piexels). Each string is connected to a different port (i.e. PORTA.0, PORTA.1, PORTA.2 and PORTA.3 )
Currently, I can address one string (one PORT) and the code works...for one string. I cannot make three more copies of the code in my PIC. Instead, if I could address all four ports by the help of a variable (all other possible solution), my clock would already be hanging on my wall.
Hope this helps to slightly getting something to see through the mist...
I would be tempted to use one pin as the output and then feed that into the anodes of four diodes with the cathodes of those four diodes connected to a set of four 470R resistors. The junctions of the diodes/resistors fed to your WS2812B's and the 'free' end of the resistors connected to four additional pins on the PIC. By setting one of the relevant pins low, that output will go high/low as the code sets the output for the WS2812B, with all three of the other pins set high, those connections to the WS2812B will stay high and not send any data. A simple diode multiplexer.
Worth a try?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It seems that #include WILL NOT do what you want. See later in this post.
Use the work around attached. This uses two macros to do the same, I have made this compile but this will be a lot easier to get going.
I have added 32mHz to the frequency, I am not sure if you have tested on real silicon but you would need to add the correct CONFIG statements for 40Mhz.
I also removed the #ASMRAW as this is not required and was incorrect used anyway.
A few things other things I would do.
Change the chip to a modern chip that is a lot faster.
Use the demo demos\LED_Solutions\LED_WS2812\WS2812_LED_using_BitBanging-18f14k22.gcb this will then remove the reliance on NOPs and move to a proper time based interrupt solution.
This demo will remove the reliance on have to populate the arrays NeoGreen(), NeoBlue() and NeoRed() as this is very slow.
WS2812B_18F1330_C.gcb works. I get that but I think the demo is a lot faster and using WS2812BitBangSendData to improve performance.
Do a search on YouTube for GCBASIC | Great Cow BASIC and WS2812. MKStevo, myself and others have posted using the libraries in the demo. https://www.youtube.com/watch?app=desktop&v=HX5B5dytBzM
Why Include did not work in this very specific case = unstructured code
In GCBASIC, any code that is not placed within a structure like a subroutine, function, or macro will not be compiled because the compiler expects all executable code to be organized within these structures. This design ensures that the code is modular, maintainable, and easier to debug.
Here are a few reasons why this approach is used:
Modularity: By requiring code to be within subroutines, functions, or macros, GCBASIC promotes modular programming. This makes it easier to manage and understand the code, especially in larger projects.
Scope Management: Placing code within structures helps manage variable scope effectively. None byte variables declared within a subroutine or function are scoped to that block, preventing unintended interactions with other parts of the program.
Error Handling: Structured code allows for better error handling and debugging. If an error occurs, it is easier to trace and fix within a well-defined block of code.
Reusability: Functions and macros can be reused throughout the program, reducing redundancy and making the code more efficient.
Essentially, the code within WS2812B_18F1330_B.gcb and WS2812B_18F1330_C.gcb is not structured, never called and therefore removed from the end to end program when your program is optimised.
This can be proved with your sources.
Editing file A to call a macro defined in file B 'macroB'
Editing file B to
Leave one #include
Edit all calls to #INCLUDE "WS2812B_18F1330_C.gcb" to be MacroC
Top and tail fileB with the macro definition for 'macroB'
Edit file C
Top and tail fileC with the macro definition for 'macroC'
Now... you will try to compile and you will get a syntax error, so, edit out all the #RAWASMs.
Hi All,
I'm wondering if it is possible to assign a different PORT to a same variable like this example
Is this doable in GCB?
Well yes.
But, so points though.
if PortPin is a constant. If the constant is a port.pin the will be assigned the bit value of porta.x
If PortPin is a bit variable. It will assigned to bit value of porta.x
If PortPin is a byte variable. It will be assigned 1 or 0 that is the value of porta.x
Compile a program and try. See what happens.
what about:
IF Value = 1 THEN
PortPin = 0
ELSE
PortPin = 1
END IF
This code obviously only changes the port's state which is not what I'm looking for.
I'm currently looking into Anobium's advice....
Anobium,
I'm starting with GCB so my knowledge of its syntax is not that great for the moment.
This is my code, not working.
How do I declare a port pin as "variable"? I don't know how to declare it as a bit, btw...
I'm a little confused here.
Last edit: Flotul 2024-08-01
You need to set the DIRection of the port.
Dir NeoPin Out
And, yes.. you created a CONSTANT.
Your code is highly costly in terms of program memory. Whilst you may not know IDX bit value there are many ways to make this better.
You can read the port into a varaible and set the variable.bit and then set the port.
Use a select Case.
Read the port and rotate to set the bit. The hardest to understand, the fastest.
There are other waysm but the above method works but is slow.
This is probably the fastest loop:
Do
neopin=!Neopin
Wait 500 ms
Loop
Thanks Chris but this is still not what I'm asking for.
So, looking back to my first post, I could have asked otherwise like this:
Is it a little more clear now? Actually, I can't make that work.
Again, to avoid the need of copying tons of code, I have made one subroutine where I then set the needed port.
Now that I have a better understanding of your intent, I can see that you are on totally the wrong track.
All you are doing is assigning a value to a variable called portpin.
What you are attempting to do is assign a value, that is the address of a port, to a variable called portpin and then use that variable to indirectly address a bit within that port.
In short It can't be done in GCBasic in the way that you thought, however, you can work around it in GCBasic by embedding assembler code into your basic code to indirectly address the hardware.
You will lose all portability, and will have to have a good understanding of the Datasheet for the device you are trying to program, but it can be done.
You may also want to try the Help pages and look for Indirect addressing, you may find some answers there which could alleviate the burden of assembly programing.
Cheers
Chris
I also found this post that may solve your problems:
https://sourceforge.net/p/gcbasic/discussion/579125/thread/41bb58f4/
Cheers
Chris
Guys.
This code needs way more clarification before ASM is needed.
~~~
Dim PortPin as Byte ' this variable is ment to represent a PORT
If a condition is true Then
PortPin = PORTA.0
Else
PortPin = PORTC.4
Endif
Sub mySub
Do
neopin=!Neopin
Wait 500 ms
Loop
End Sub
~~~~
What is actually meant to happen?
if some condition is true then the Byte variable is meant to be what? is bit.0 meant to be the state of porta.0 or portc.4 ? or, is variable meant to be 0 or 255? should this be PortPin as a Bit? should this be PortPin.0?
What is happening in the sub? Some other ram register or some other io register is toggling? What has this to with solution as this is an endloop?
I actually opened another thread about #Include/#Insert but it is all for the same project.
So please find here my project and it might help to understand why I'm currently doing the way...it is done. @20MHz, there is a huge timing issue (meaning there is no space at all for GOSUBs, GOTOs et so forth) using the WS2812B NeoPixel strings reason why I have some ultra simple assembler code in it.
My wall clock has four digits made of each a NeoPixel string (4x 28 piexels). Each string is connected to a different port (i.e. PORTA.0, PORTA.1, PORTA.2 and PORTA.3 )
Currently, I can address one string (one PORT) and the code works...for one string. I cannot make three more copies of the code in my PIC. Instead, if I could address all four ports by the help of a variable (all other possible solution), my clock would already be hanging on my wall.
Hope this helps to slightly getting something to see through the mist...
https://sourceforge.net/p/gcbasic/discussion/579125/thread/c9bfa9bf93/1d24/attachment/WS2812B_18F1330_A.zip
I would be tempted to use one pin as the output and then feed that into the anodes of four diodes with the cathodes of those four diodes connected to a set of four 470R resistors. The junctions of the diodes/resistors fed to your WS2812B's and the 'free' end of the resistors connected to four additional pins on the PIC. By setting one of the relevant pins low, that output will go high/low as the code sets the output for the WS2812B, with all three of the other pins set high, those connections to the WS2812B will stay high and not send any data. A simple diode multiplexer.
Worth a try?
Thanks Ccin E Crout , why not?
The downside here is the "loss" of one port but that might be the cost it takes.
It seems that #include WILL NOT do what you want. See later in this post.
Use the work around attached. This uses two macros to do the same, I have made this compile but this will be a lot easier to get going.
I have added 32mHz to the frequency, I am not sure if you have tested on real silicon but you would need to add the correct CONFIG statements for 40Mhz.
I also removed the #ASMRAW as this is not required and was incorrect used anyway.
A few things other things I would do.
Change the chip to a modern chip that is a lot faster.
Use the demo demos\LED_Solutions\LED_WS2812\WS2812_LED_using_BitBanging-18f14k22.gcb this will then remove the reliance on NOPs and move to a proper time based interrupt solution.
This demo will remove the reliance on have to populate the arrays NeoGreen(), NeoBlue() and NeoRed() as this is very slow.
WS2812B_18F1330_C.gcb works. I get that but I think the demo is a lot faster and using WS2812BitBangSendData to improve performance.
Do a search on YouTube for GCBASIC | Great Cow BASIC and WS2812. MKStevo, myself and others have posted using the libraries in the demo.
https://www.youtube.com/watch?app=desktop&v=HX5B5dytBzM
Why Include did not work in this very specific case = unstructured code
In GCBASIC, any code that is not placed within a structure like a subroutine, function, or macro will not be compiled because the compiler expects all executable code to be organized within these structures. This design ensures that the code is modular, maintainable, and easier to debug.
Here are a few reasons why this approach is used:
Modularity: By requiring code to be within subroutines, functions, or macros, GCBASIC promotes modular programming. This makes it easier to manage and understand the code, especially in larger projects.
Scope Management: Placing code within structures helps manage variable scope effectively. None byte variables declared within a subroutine or function are scoped to that block, preventing unintended interactions with other parts of the program.
Error Handling: Structured code allows for better error handling and debugging. If an error occurs, it is easier to trace and fix within a well-defined block of code.
Reusability: Functions and macros can be reused throughout the program, reducing redundancy and making the code more efficient.
Essentially, the code within WS2812B_18F1330_B.gcb and WS2812B_18F1330_C.gcb is not structured, never called and therefore removed from the end to end program when your program is optimised.
This can be proved with your sources.
Editing file A to call a macro defined in file B 'macroB'
Editing file B to
Leave one #include
Edit all calls to #INCLUDE "WS2812B_18F1330_C.gcb" to be MacroC
Top and tail fileB with the macro definition for 'macroB'
Edit file C
Top and tail fileC with the macro definition for 'macroC'
Now... you will try to compile and you will get a syntax error, so, edit out all the #RAWASMs.
It should compile.
Last edit: Anobium 2024-08-04
This is a very interesting use case.
Thank you for posting the source. I now understand what is going on.
:-)
Evan
Thanks a lot Evan.
As I'm a little short in time, I made my proto this week-end using five separate µCs, one as MASTER and four as SLAVEs (see pictures).
I even used my crapy code but, at the end of the day, it works.
And thank you for explaining the use of GCB. I'm new to it so I have a lot to discover.
Looks great.
I am interested in seeing final program. Please share.
I will do...but it will still be in PICBASIC for now...