Confused by Char / String usage

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

Post Reply
SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

Confused by Char / String usage

Post by SHughes_Fusion » Mon Sep 01, 2014 11:21 am

I'm trying to copy the contents of a Const string one character at a time in to a byte array but I'm hitting some very confusing problems.

This isn't my whole program but I have:

Code: Select all

Public Const VersionStr = "0.3.1"
Dim tBuf(10) As Byte, bCount As Byte
Dim tVar As Char
  
bCount = 0
Repeat
  tVar = VersionStr(bCount) 
  Inc(bCount)
Until VersionStr(bCount) = null
I get an error on the line tVar = VersionStr(bCount) where it complains about incompatible types.

Surely I should be able to set a Char variable equal to one character from a string?

I've not done this specifically that I can find, but I've just String(element) as a parameter in a function call that is expecting a Char.

What am I doing wrong? I did try typecasting directly in to the tBuf array but it seems you can't use typecasting with array elements.

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Confused by Char / String usage

Post by Jerry Messina » Mon Sep 01, 2014 12:41 pm

const strings are a bit funny... they don't seem to follow the "normal rules", but maybe it's me.

You would think what you're doing should be ok, but it doesn't work. Neither does just declaring the const as a string
ie: const MyStr as string = "ABC"

I've found two ways around it:
- copy the const to a string variable (which seems a bit of a waste, and generates a fair bit of code)

Code: Select all

dim s as string

s = VersionStr
bCount = 0
while (s(bCount) <> null)
  tVar = s(bCount)
  Inc(bCount)
end while
- use the pic18 TABLEPTR and instructions to access the data

Code: Select all

// this declaration should already exist in the device include file, so not needed
'dim TABLEPTR as TBLPTRL.AsWord

// read flash at current TABLEPTR
inline function ReadROM() as TABLAT
    asm
        TBLRD *
    end asm
end function

// read flash with autoincrement of TABLEPTR
inline function ReadROMstring() as TABLAT
    asm
        TBLRD *+
    end asm
end function

// copy rom string one char at a time, skipping NULL
TABLEPTR = addressof(VersionStr)
Repeat
  tVar = ReadROMstring()
Until (ReadROM() = byte(null))

SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

Re: Confused by Char / String usage

Post by SHughes_Fusion » Mon Sep 01, 2014 3:04 pm

Thanks, Jerry, I'll have a play with that way of accessing them.

String constants seem to have some serious shortcomings in Swordfish - I'm trying to rewrite a routine to accept a pre-defined string by ref - using ByRefConst - and while it works OK with arrays it won't work at all with strings, just keeps saying can't be passed by reference.

Looking at the .asm it looks like I should be able to save a lot of code and RAM space if I can get this working as I use the function quite a lot and it uses 56 instructions just to call it!

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Confused by Char / String usage

Post by Jerry Messina » Mon Sep 01, 2014 3:26 pm

maybe something like this?

Code: Select all

//
// access a const string
//
const VersionStr = "1.0.2"

sub print_cstr(rom_addr as word)
    dim b as byte

    TABLEPTR = rom_addr
    Repeat
      b = ReadROMstring()
    Until (ReadROM() = byte(null))
end sub
    
print_cstr(@VersionStr)
print_cstr(@("this is a test"))

You can even alias the rom_addr variable and have it put directly into TABLEPTR...

Code: Select all

sub print_cstr(rom_addr as TABLEPTR)
    dim b as byte

    Repeat
      b = ReadROMstring()
    Until (ReadROM() = byte(null))
end sub

SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

Re: Confused by Char / String usage

Post by SHughes_Fusion » Mon Sep 01, 2014 3:47 pm

I'm actually trying something like that now. Doesn't actually save as much code space as I imagined! And it's not ideal having one sub for printing one type of data and a different one for another, especially when you can't overload them.

Not sure also if I'm worrying too much at the moment - I'm still only 2/3 the way through the processor resources and the software is 95% done. I just don't like doing things suboptimally...

I'm actually considering starting a thread to share advice on optimising Swordfish code as I've found plenty of ways to reduce size. For example, the Bootloader I wrote a few weeks back comes in at under 2k when manually optimised but if I'd stuck with using library functions it would have ended up nearly twice the size. Even then there are some things it looks like I could optimise further if I understood enough about working in assembler. Things like it appears if a variable is referenced twice in succession then Swordfish often seems to load it in to the same register both times. I wonder if that could be optimised but it probably isn't worth the time of looking deeply in to the code to make sure it might not get changed between.

Is it documented anywhere what, if any, optimising Swordfish actually does?

SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

Re: Confused by Char / String usage

Post by SHughes_Fusion » Mon Sep 01, 2014 3:55 pm

Back to the drawing board!

The modified functions didn't work and I'm pretty sure I know why...

The output is to a graphical LCD. The WriteChar routine I use accesses a font table which is also stored in ROM so I'd guess Swordfish is modifying the table pointer itself...

Post Reply