I have attached the demo program in question and want to know how the value of " HiAddr " is derived.
Maybe the default value of a variable that is not given a value is zero...
HiAddr is a value given to the subroutine as a parameter.
So.
If you wanted to write a value of 1,234,567 to EeProm location 0 (zero) you would call the routine like this:
'PutLEeprom(Value for HiAddr, Value to store in EeProm)PutLEeprom(0,1234567)'Location "0" (zero) is placed into variable HiAddr.'Value 1234567 is placed into Save_Long
This would store the value 1234567 across four byte locations in Eeprom. Those locations being
Location 0
Location 1
Location 2
and
Location 3
For retrieving the value stored in EeProm, you would call the routine like this:
LetLong_Returned=GetLEeprom(0)
Again the passed value of "0" is placed into HiAddr.
Long_Returned is then filled with the contents of EeProm locations 0, 1, 2 and 3.
Hope that makes sense.
Last edit: mkstevo 2021-05-14
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I should perhaps point out that the SubRoutine declaration:
Sub PutLEeprom (HiAddr As Byte, Save_Long As Long)
Effectively dimensions ("Dim") the variables HiAddr (as a Byte value) and Save_Long (as a Long value).
In other languages, the variables HiAddr and Save_Long would only exist within the PutLEeprom subroutine and would cease to exist once the sub exits. In GCB basic this doesn't happen and these (and all) variables have global existance, and so are available to the entire program. I try not to use the variables declared this way elsewhere in a program as the values will be overwritten by any call to the subroutine.
Having had odd effects happen with parameters passed to a subroutine, I now try to declare subroutines with any parameters using the "In" statement:
Sub PutLEeprom (In HiAddr As Byte, In Save_Long As Long)
This can prevent variable values passed as a parameter being altered by the subroutine. This only happens very rarely, but using "In" seems to stop it happening at all.
Last edit: mkstevo 2021-05-13
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
For me, it simplifies my program and suits my thought process.
If I call:
PutLEeprom( 0, 1234567 )
It is clear to me that the value will be stored in location 0 (and 3,4,5)
If I then call:
PutLEeprom( 4, 7654321 )
It is clear to me that the value will be stored in location 4 (and 5,6,7)
I also use parameters to call "different" versions of a subroutine. I wrote a subroutine recently for generating some low frequency PWM. I can call this with parameters for frequency, duty cycle and polarity. Again, this allows me to reuse the same subroutine for various situations that might require positive going PWM duties or negative duties.
Going further, by defining some constants the use of a subroutine call becomes even more obvious:
Pseudo code follows
#DefineFiftyHz50#DefineHundrHz100#DefineKiloHz1000#DefineFiftyPercent50#DefineSixtyPercent60#DefineSeventyPercent70#DefinePosPWM0#DefineNegPWM1GeneratePWM(FiftyHz,SixtyPercent,PosPWM)GeneratePWM(HundrHz,SeventyPercent,PosPWM)GeneratePWM(KiloHz,FiftyPercent,NegPWM)SubGeneratePWM(InPWMFrequencyAsWord,InDutyCycleAsByte,InPWMPolarityAsByte)IfPWMPolarity>1ThenLetPWMPolarity=0EndIfIfDutyCycle<1ThenLetDutyCycle=1EndIfIfDutyCycle>98ThenLetDutyCycle=99EndIf'Do the PWM generation hereEndSub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
To some degree, you could omit the parameters totally.
Let us assume that the function and subroutine for saving and retrieving a long value from EeProm have been written with the sub and variables declared like this:
DimHiAddrAsByteDimSave_LongAsLongSubPutLEeprom'Section for storing the parts of a Long value'into consecutive bytes in EeProm hereEndSub
You could then do this:
LetHiAddr=0LetSave_Long=1234567PutLEeprom
Which is in essence what the original call does when it is called in the first example I gave:
PutLEeprom(0,1234567)
To my mind, the second example is easier to understand. It looks more obvious to me that the values "0" and "1234567" are related to putting a long value into eeprom.
That is not to say that either technique is "better" or "worse" than the other, but passing them as parameters is my preferred method, it suits me.
If you prefer another method that does the same thing, that is fine, what you prefer is right for you.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Great Cow BASIC will share memory locations with many variables when passing items are parameters, and, the optimiser will try to rationalise memory.
And, it is a good practice - in a sub/function the variable may have a different name to help understanding of the method, whilst using the same memory location as the passed parameter.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The following suggestions by me turned out to be incorrect. I have left them only to show the context of Jerry's further comments, and my misunderstanding!
I will (should) let Anobium answer this, as I don't want to put words in his mouth.
I wonder if he meant that if you call a subroutine with a named variable passed as one of the parameter values the named variable is sometimes used directly rather than copied to the parameter name (which could explain why passing variables to subroutines can sometimes cause them to be corrupted) and a copy of that value used within the subroutine.
So possibly, in the example below, MyVarAddr and MyVarLong would not be "copied" into HiAddr and SaveLong but actually "be assimilated into" HiAddr and SaveLong, sharing the memory addresses?
DimMyVarAddrAsByteDimMyVarLongAsLongLetMyVarAddr=0LetMyVarLong=1234567PutLEeprom(MyVarAddr,MyVarLong)SubPutLEeprom(HiAddrAsByte,SaveLongAsLong)'Section for storing the parts of a Long value'into consecutive bytes in EeProm hereEndSub
Although, like you, I could be missing something too!
Quote by Anobium: There is no assimilation.
Last edit: mkstevo 2021-05-15
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
So possibly, in the example below, MyVar_Addr and MyVar_Long would not be "copied" into HiAddr and Save_Long but actually "be assimilated into" HiAddr and Save_Long, sharing the memory addresses?
Something like that sounds a bit scary to me!
I agree that the "PutEeprom(param, param)" style is preferable, but if it's just syntactical sugar that's good to know.
GCB wouldn't be the first compiler to make everything global in nature... just trying to understand the rules. If "local" variables aren't shared then that can have a big impact on total ram usage, but I understand the complexities involved.
Thanks.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am currently travelling away from home on a very serious matter. If you post the code in question again (I cannot find the initial example below). I can look for you.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
ditto. when I dim vars they work in all my program. I know that variables are changed to aliases yo use gcb includes but what us wrong with dim vars at start of code and they work in that code?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
PutLEeprom(0,1234567)'other code here...SubPutLEeprom(HiAddrAsByte,Save_LongAsLong)'Section for storing the parts of a Long value'into consecutive bytes in EeProm hereEndSub
Is easier to understand than
DimHiAddrAsByteDimSave_LongAsLongLetHiAddr=0LetSave_Long=1234567PutLEeprom'other code here...SubPutLEeprom'Section for storing the parts of a Long value'into consecutive bytes in EeProm hereEndSub
Horses for courses, but the first example to my eye is more readable and has more flexibility, even more so with the PWM example further up this thread.
If it were possible to have true "Local" variables with explicit limited scope I would be even happier!
Last edit: mkstevo 2021-05-14
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have attached the demo program in question and want to know how the value of " HiAddr " is derived.
Maybe the default value of a variable that is not given a value is zero...
HiAddr is a value given to the subroutine as a parameter.
So.
If you wanted to write a value of 1,234,567 to EeProm location 0 (zero) you would call the routine like this:
This would store the value 1234567 across four byte locations in Eeprom. Those locations being
Location 0
Location 1
Location 2
and
Location 3
For retrieving the value stored in EeProm, you would call the routine like this:
Again the passed value of "0" is placed into HiAddr.
Long_Returned is then filled with the contents of EeProm locations 0, 1, 2 and 3.
Hope that makes sense.
Last edit: mkstevo 2021-05-14
I should perhaps point out that the SubRoutine declaration:
Sub PutLEeprom (HiAddr As Byte, Save_Long As Long)
Effectively dimensions ("Dim") the variables HiAddr (as a Byte value) and Save_Long (as a Long value).
In other languages, the variables HiAddr and Save_Long would only exist within the PutLEeprom subroutine and would cease to exist once the sub exits. In GCB basic this doesn't happen and these (and all) variables have global existance, and so are available to the entire program. I try not to use the variables declared this way elsewhere in a program as the values will be overwritten by any call to the subroutine.
Having had odd effects happen with parameters passed to a subroutine, I now try to declare subroutines with any parameters using the "In" statement:
Sub PutLEeprom (In HiAddr As Byte, In Save_Long As Long)
This can prevent variable values passed as a parameter being altered by the subroutine. This only happens very rarely, but using "In" seems to stop it happening at all.
Last edit: mkstevo 2021-05-13
And a final comment...
The EeProm can only store Byte values. The Long value has to be broken into byte values to store it in EeProm.
Trying to store a whole "Long" value directly in EeProm will cause it to be truncated to a Byte value.
Which is why the routine was originally written!
Is this really true?
If so, what's the point in "passing parameters"? Why use parameters at all?
For me, it simplifies my program and suits my thought process.
If I call:
PutLEeprom( 0, 1234567 )
It is clear to me that the value will be stored in location 0 (and 3,4,5)
If I then call:
PutLEeprom( 4, 7654321 )
It is clear to me that the value will be stored in location 4 (and 5,6,7)
I also use parameters to call "different" versions of a subroutine. I wrote a subroutine recently for generating some low frequency PWM. I can call this with parameters for frequency, duty cycle and polarity. Again, this allows me to reuse the same subroutine for various situations that might require positive going PWM duties or negative duties.
Going further, by defining some constants the use of a subroutine call becomes even more obvious:
Pseudo code follows
To some degree, you could omit the parameters totally.
Let us assume that the function and subroutine for saving and retrieving a long value from EeProm have been written with the sub and variables declared like this:
You could then do this:
Which is in essence what the original call does when it is called in the first example I gave:
To my mind, the second example is easier to understand. It looks more obvious to me that the values "0" and "1234567" are related to putting a long value into eeprom.
That is not to say that either technique is "better" or "worse" than the other, but passing them as parameters is my preferred method, it suits me.
If you prefer another method that does the same thing, that is fine, what you prefer is right for you.
The answer is memory management and optimisation.
Great Cow BASIC will share memory locations with many variables when passing items are parameters, and, the optimiser will try to rationalise memory.
And, it is a good practice - in a sub/function the variable may have a different name to help understanding of the method, whilst using the same memory location as the passed parameter.
Maybe I'm missing something (wouldn't be the first time).
Doesn't that conflict with what mkstevo said?
If variables can share memory locations then how can they be global in scope?
I was indeed missing something, so will wait for Anobium to expand on his comment:
The following suggestions by me turned out to be incorrect. I have left them only to show the context of Jerry's further comments, and my misunderstanding!
I will (should) let Anobium answer this, as I don't want to put words in his mouth.
I wonder if he meant that if you call a subroutine with a named variable passed as one of the parameter values the named variable is sometimes used directly rather than copied to the parameter name (which could explain why passing variables to subroutines can sometimes cause them to be corrupted) and a copy of that value used within the subroutine.
So possibly, in the example below, MyVarAddr and MyVarLong would not be "copied" into HiAddr and SaveLong but actually "be assimilated into" HiAddr and SaveLong, sharing the memory addresses?
Although, like you, I could be missing something too!
Quote by Anobium: There is no assimilation.
Last edit: mkstevo 2021-05-15
Something like that sounds a bit scary to me!
I agree that the "PutEeprom(param, param)" style is preferable, but if it's just syntactical sugar that's good to know.
GCB wouldn't be the first compiler to make everything global in nature... just trying to understand the rules. If "local" variables aren't shared then that can have a big impact on total ram usage, but I understand the complexities involved.
Thanks.
There is no assimilation.
I am currently travelling away from home on a very serious matter. If you post the code in question again (I cannot find the initial example below). I can look for you.
ditto. when I dim vars they work in all my program. I know that variables are changed to aliases yo use gcb includes but what us wrong with dim vars at start of code and they work in that code?
Because I still think that
Is easier to understand than
Horses for courses, but the first example to my eye is more readable and has more flexibility, even more so with the PWM example further up this thread.
If it were possible to have true "Local" variables with explicit limited scope I would be even happier!
Last edit: mkstevo 2021-05-14
I don't know why vars get changed . if I dim var1 as byte why can't it stay like that?
Last edit: stan cartwright 2021-05-14
I'm not sure what you mean Stan?
Once a variable has been dimensioned its type doesn't normally change?
But vars are given aliases and I thought they were global through my code but I hear off local variables which makes gcb harder.
As far as I am aware there are no local variables in GCB, all are global in scope.
Aliases are something else again.