Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Using variables in Libraries?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR
View previous topic :: View next topic  
Author Message
jacksan

Bascom Member



Joined: 28 Jan 2005
Posts: 93

blank.gif
PostPosted: Tue Dec 04, 2018 4:04 pm    Post subject: Using variables in Libraries? Reply with quote

I'm using the purchased long-range 1-Wire library: 1wire_4pin.lib ... Excellent library!

The library contains this statement which set delays: @genus(9)
I would like to be able to adjust this timing by using a variable in the BASCOM code.

It works if I use a constant:
BASCOM:
const cTimeDelay = 12
LIBRARY:
@genus(cTimeDelay)

This syntax also works in the Library:
*BASIC: WAITUS 12


I cannot get variables to work:
BASCOM:
dim cTimeDelay as byte (or integer)
cTimeDelay = 12


LIBRARY:
@genus(cTimeDelay) Produces a compile error in the Library: Illegal character [expected (, got '' [cTimeDelay]]


Or, LIBRARY:
*BASIC: WAITUS cTimeDelay Produces a compile error in the Library: Label not found [_MICRO_DELAY]


Thoughts?

(BASCOM-AVR version : 2.0.8.1 )
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 1599

blank.gif
PostPosted: Tue Dec 04, 2018 8:34 pm    Post subject: Reply with quote

Lib:
Code:
[test]
Test:

*BASIC: waitus w

RET
[end]

Program:
Code:
$Regfile="m328pdef.dat"
$Crystal=16000000
$hwstack=40
$swstack=16
$framesize=32


$LIB"test.lib"
$external test

Dim w As Byte
w = 1
waitus w' dummy call, required to get _micro_delay included

Declare Sub test

Do

w = 50

call test

w = 150

call test

Loop
Back to top
View user's profile
jacksan

Bascom Member



Joined: 28 Jan 2005
Posts: 93

blank.gif
PostPosted: Wed Dec 05, 2018 9:20 pm    Post subject: Reply with quote

I can't get it to work.

In your example you use the following 3 statements. I'm thinking(?) I don't need them because they are already being called as part of the 1-Wire functionality.
Code:
$external test
...
Declare Sub test
...
call test

That leaves me with...
1wire_4pin.lib Library:
Code:
[_1WIRE]
...
*BASIC: waitus cReadTimeDelay
...
Ret

BASCOM:
Code:
$lib "1wire_4pin.lib"
dim cReadTimeDelay as byte
cReadTimeDelay = 21
waitus cReadTimeDelay

It now compiles fine, but the values is being set to zero.
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 4660
Location: Holland

blank.gif
PostPosted: Wed Dec 05, 2018 9:43 pm    Post subject: Reply with quote

waitus used with a variable will trash R30 and R31
So you need to save/restore them.
Before the call to waitus using the variable, add this :

Push R30
Push R31
basic call with waitus
Pop R31
Pop r30

waitus with a constant does not alter registers.

_________________
Mark
Back to top
View user's profile Visit poster's website
jacksan

Bascom Member



Joined: 28 Jan 2005
Posts: 93

blank.gif
PostPosted: Wed Dec 05, 2018 10:59 pm    Post subject: Reply with quote

I tried...
LIBRARY:
Code:
[_1WIRE]
...
Push r30
Push r31
*BASIC: waitus cReadTimeDelay
Pop r31
Pop r30  
...
Ret
 

Undid that, and then tried:
BASCOM:
Code:
!Push r30
!Push r31
totalCount = 1wirecount()         'this calls the library
!Pop r31
!Pop r30


Still no success
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 1599

blank.gif
PostPosted: Thu Dec 06, 2018 9:19 am    Post subject: Reply with quote

albertsm wrote:
waitus used with a variable will trash R30 and R31

R30/31 is used as counter for the delay, but to retrieve the pointer for the variable, also R26/R27 is destroyed.
Based on this, the lib in my example needs to look like this:
Code:
Push R26
Push R27
Push R30
Push R31
*BASIC: waitus w
Pop R31
Pop R30
Pop R27
Pop R26

Another option would be to make your own small delay loop within your lib based on ASM.
Back to top
View user's profile
jacksan

Bascom Member



Joined: 28 Jan 2005
Posts: 93

blank.gif
PostPosted: Thu Dec 06, 2018 3:14 pm    Post subject: Reply with quote

Same problem, the variable is trashed.

I found something that might be important:
This does not work with a constant either:
LIBRARY:
Code:
*BASIC: waitus cReadTimeDelay
 
If it doesn't work with a constant, I'd guess(?) that it won't work for a variable either.

This command is what works with a constant:
LIBRARY:
Code:
@genus(cReadTimeDelay)
But it won't compile when using Push/Pop:
Compile error when using a Constant: Forward jump out of range [_1WIRE_WRITE_BIT0 [ 69]]
Compile error when using a Variable: -13137 Illegal character [expected (, got '' [cReadTimeDelay]]
So using @genus with a variable is probably not possible:


Bascom declations used:
Code:
'Variable:
dim cReadTimeDelay as byte
cReadTimeDelay = 21
waitus cReadTimeDelay

'Or Constant:
const cReadTimeDelay = 21                                                        
waitus cReadTimeDelay


I'm still not finding a way to use a Basic variable in a Library for waitus/@genus.
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 1599

blank.gif
PostPosted: Thu Dec 06, 2018 6:17 pm    Post subject: Reply with quote

jacksan wrote:
Same problem, the variable is trashed.

You use 1wire, which is picky in regards of timing. You may have two road-works, one where you tamper around with delays to make that run, and the other one is your secret sensor, device, whatsoever thingy.
Obviously you need to get rid of one of your roadworks, otherwise you will never know where's the bug.

I suggest to share more information what you're trying to achieve, as better advice is possible then.
Also I hate it to do riddles, where it's your job of giving complete details.

To get one roadwork finished, here is a routine that works with variables, is neutral about registers and can be placed in the lib of your choice.

test.lib:
Code:
[customdelay]
cdely:
PUSH ZH
PUSH ZL
*LDS  ZL, {cdval+0}
*LDS  ZH, {cdval+1}
cdely_loop:
SBIW ZL, 1
BRNE cdely_loop
POP ZL
POP ZH
RET
[end]

Program:
Code:
$Regfile = "m328pdef.dat"
$Crystal=16000000
$hwstack=40
$swstack=16
$framesize=32


$LIB "test.lib"
$external customdelay

Dim cdval As Word
Declare Sub cdely

Do

cdval = 2
call cdely

Loop

It is not that comfortable, as you can not provide Ás parameters, instead you need to calculate the delay yourself.
Routine delays are given in processor cycles, my sample ÁC as declared does 16 millions cycles per second.

Minimum value for cdval: 1
Maximum value for cdval: 65535
Overhead of [customdelay]: 22 cycles
Delay for one increase in cdval: 4 cycles

Formula: delayed cycles = 22 + ((cdval -1) x 4)

Examples:
cdval = 2 --> 26 cycles@16MHz = 1.625 Ás
cdval = 1024 --> 4114 cycles@16MHz = 257.125 Ás
cdval = 65535 --> 262158 cycles@16MHz = 16.385 ms
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 4660
Location: Holland

blank.gif
PostPosted: Thu Dec 06, 2018 8:28 pm    Post subject: Reply with quote

i can only add that indeed r26/r27 must be saved as well.
And it simply works.

Here is what i did :


Code:
Dim Bmydelay As Byte
Bmydelay = 10
Waitus Bmydelay

Config 1wire = Portb.4 , Extended = 2 , Drive = Portb.3 , Dpu = Portb.2 , Spu = Portb.5
 



This is how you can test that the variable is indeed loaded :

_reset_1wire:
*BASIC: PRINT bMYDELAY

If you run the simulator you see that it will print 10 when executing 1wreset

And to use it without destroying registers :

Code:
Push R26
Push R27
Push R30
Push R31
*BASIC: waitus bMydelay
Pop R31
Pop R30
Pop R27
Pop R26


Take in mind that a genus does not have the extra r26/r27 save/restore. So when using a low crystal oscillator frequency you get other timing.

_________________
Mark
Back to top
View user's profile Visit poster's website
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 1599

blank.gif
PostPosted: Thu Dec 06, 2018 10:57 pm    Post subject: Reply with quote

albertsm wrote:
And to use it without destroying registers :

Code:
Push R26
Push R27
Push R30
Push R31
*BASIC: waitus bMydelay
Pop R31
Pop R30
Pop R27
Pop R26

As well I gave the TO another delay option, while knowing above works, the TO's problems very likely results out of his failing experiments of altering the timing.
He botchers the lib-code, which got its timing not just for fun, but because it was tested working this way.
To alter something to adapt it better to ones needs can be called tinkering, while randomly trial and error may be called botching.
As I just followed this up and tested it:
jacksan wrote:
Same problem, the variable is trashed.

I found something that might be important:
This does not work with a constant either:
LIBRARY:
Code:
*BASIC: waitus cReadTimeDelay
 
If it doesn't work with a constant, I'd guess(?) that it won't work for a variable either.

Found it perfectly working with a constant, of course by PUSHing/POPing the used registers, my conclusion is the TO seems to be in the botcher-phase.
I like problem-solving, but with a non-responsive TO it's boring and that's the reason it stops here for me.
Back to top
View user's profile
jacksan

Bascom Member



Joined: 28 Jan 2005
Posts: 93

blank.gif
PostPosted: Fri Dec 07, 2018 12:19 am    Post subject: Success ! Reply with quote

Success!
Sincere thanks to both of you for your assistance.

I couldn't post much of the library code since it is the purchased library from MCS.

I previously succeeded in reading a long 1-wire network using the MCS addon library with the Maxim reference schematic #244. It is working at over 300m in various noisy environments!
The key was to adjust a read-delay in the library to compensate for the slow rise-times on long cables.
I'm familiar with 1-Wire timing specs and had determined the exact values needed using a scope. Didn't really need to tinker much. Rolling Eyes
This is my first attempt at ASM, so yes, "botching" the ASM.

I ended up using MWS's loop code.
The example and formula were spot on.

The Push/Poke would not work for me... and I agree, the problem is on my end.
*BASIC: PRINT bMYDELAY tells me that the variable is making it into ASM, as both of you said.
I get quite unusual "Forward jump out of range" compile errors when I shouldn't. Such as after simply removing the "; wait at CR" comment from *BASIC: waitus bMydelay ;wait at CR
Maybe it's time to tinker with the stack/frame sizes. Wink

Working lib codelet:
Code:
[_1WIRE]
...
;@genus(9)                         ; wait at CR
PUSH ZH
PUSH ZL
*LDS  ZL, {readDelay+0}
*LDS  ZH, {readDelay+1}
cdely_loop:
SBIW ZL, 1
BRNE cdely_loop
POP ZL
POP ZH
...
ret
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 1599

blank.gif
PostPosted: Fri Dec 07, 2018 12:32 pm    Post subject: Re: Success ! Reply with quote

jacksan wrote:
I get quite unusual "Forward jump out of range" compile errors..
Maybe it's time to tinker with the stack/frame sizes.

No, stack/frame would be botching in this case, looking up the lib line number the compiler indicates as erroneous would be tinkering.
And replacing the too short jumping opcode with it's longer range counterpart will then solve it.

Likely the culprit is a conditional relative branch opcode like BREQ, BRNE, BRCS, etc., these opcodes have a range of -64/+63 words to jump over.
If too much new code is added within the jump-range, it gets out of range. In case the range is already stressed, one more command can break the jar.
Back to top
View user's profile
jacksan

Bascom Member



Joined: 28 Jan 2005
Posts: 93

blank.gif
PostPosted: Fri Dec 07, 2018 6:45 pm    Post subject: Success #2 Reply with quote

The Push/Pop is also working now!

MWS pointed me in the right direction regarding branches (BRTC in my case) and the "Forward Jump Out of Range" error.
This appears to be a common error. Note that the error message did not point to the correct line number.

I couldn't find anything that I (zero ASM knowledge) could botch together to make work regarding the "replacing the too short jumping opcode with it's longer range counterpart" suggestion.

You mentioned "If too much new code is added within the jump-range", and I found one vague reference to "moving code".
So i simply rearranged the lines of code in the library a little, moving the called routine closer to the BRTC, and it worked.

Is this an acceptable solution?
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 1599

blank.gif
PostPosted: Fri Dec 07, 2018 7:40 pm    Post subject: Re: Success #2 Reply with quote

jacksan wrote:
The Push/Pop is also working now!

Good to hear.
Quote:
I couldn't find anything that I (zero ASM knowledge) could botch together to make work regarding the "replacing the too short jumping opcode with it's longer range counterpart" suggestion.

Each conditional branch opcode has it's counterpart, for BRTC (branch if T-flag is cleared) it is BRTS (branch if T-flag is set).
The conditional branches can be extended with the help of a second command, RJMP or JMP.
A backward jump/branch too long situation:
Code:
label_1:
;' too many commands here
BRTC label_1,   ;' branch to label if T-flag is cleared, else follow on

Solution:
Code:
label_1:
;' a real whole lota bunch of commands here
BRTS label_2
RJMP label_1   ;' rjmp covers 2k words back jump
label_2:

Quote:
So i simply rearranged the lines of code in the library a little, moving the called routine closer to the BRTC, and it worked.

The order is most important, rearranging in terms of mixing up the opcodes may result in the most unusual behavior.
These conditional branches are like GOTOs, these are not SUBs where the SUB can moved easily, as it exits back to the caller.
I do not say that rearranging can not be done, if it is encapsulated well and exits only where it did before, this can work.
Ask yourself, if you did it this way.
Back to top
View user's profile
jacksan

Bascom Member



Joined: 28 Jan 2005
Posts: 93

blank.gif
PostPosted: Fri Dec 07, 2018 9:00 pm    Post subject: Reply with quote

got it now (finally)...
It took a minute to see what was going on.

Forward jump:
Code:
;brtc _1wire_write_bit0    ;64 word jump not enough
brts _dummyLabel           ;use brts instead of brtc. Skips over the JMP if set
jmp _1wire_write_bit0      ;2K jump
_dummyLabel:
...
_1wire_write_bit0:
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum