Double passing of strings

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

Post Reply
blackcattech
Posts: 113
Joined: Mon Jan 11, 2010 10:39 pm
Location: Chesterfield

Double passing of strings

Post by blackcattech » Wed Aug 14, 2013 2:58 pm

Working on some display driver routines I'm finding some odd behaviour with strings.

I have a function which returns the width of a character and a second function with calls this multiple times for a string and returns the width of the string. (In pixels)

I'm trying to write a sub to centralise a string on the display. However, I can't get it to centralise properly and when I do some debugging I am finding that for longer strings the width returned is garbage.

However, if I copy the same code to my main program all works as expected. The issue seems to be that I'm passing a string to the CentralStr routine which is passing it on to the WidthOfStr routine and somehow in this double-passing things are getting mangled. It works OK for short strings (< about 6 characters) but anything longer, and especially over 10 characters returns an incorrect width and therefore the string doesn't centralise properly.

Is this a known issue with Swordfish or can anyone suggest anything I may be doing wrongly?

blackcattech
Posts: 113
Joined: Mon Jan 11, 2010 10:39 pm
Location: Chesterfield

Post by blackcattech » Wed Aug 14, 2013 3:04 pm

The code is below. I've adapted the font format slightly.

Code: Select all

    // Find the width of a character. Right hand padding defaults to 1 if not specified.
    // Remember if using this to supply a fixed width to WriteChar or WriteStr that you need to specify zero padding either here or in the write command.
Public Function WidthOfChar(ByRefConst FontMap() As Byte, CNo As Byte, CPad As Byte = 1) As Byte
  Dim w, l As Word

  If CNo < FontMap(2) Then CNo = FontMap(2) EndIf                   // Set limits on the character number.
  If CNo > FontMap(3) Then CNo = FontMap(3) EndIf                   // Limit to the number of characters defined.  
  CNo = CNo - FontMap(2)                                            // Remove ASCII offset. We will end up with a character reference between 0 and the number of chrs defined.

  w = CNo * 2
  w = w + FontOffset 
  l.byte0 = FontMap(w)
  l.byte1 = FontMap(w+1)
  
  result = FontMap(l) + CPad
End Function

    // Find the width of a full string of characters
Public Function WidthOfStr(ByRefConst FontMap() As Byte, CStr As String) As Byte
  Dim sw, sl As Byte
  
  sw = 0
  sl = 0
  While CStr(sl) <> null
    sw = sw + WidthOfChar(FontMap, CStr(sl))
    Inc(sl)
  Wend
  
  result = sw  
End Function

Public Sub CentralStr(ByRefConst Fontmap() As Byte, CStr As String, YPage As Byte)
  Dim w As Byte
  
  w = D_COLUMNS - WidthOfStr(FontMap, CStr)
  w = w / 2
  w = w + D_OFFSET
  WriteStr(Fontmap, CStr, w, YPage)
End Sub
For debugging I've altered the CentralStr routine to:

Code: Select all

Public Sub CentralStr(ByRefConst Fontmap() As Byte, CStr As String, YPage As Byte)
  Dim w As Byte
  
  w = WidthOfStr(FontMap,CStr)
  WriteStr(FontMap, DecToStr(w),0,YPage)
End Sub
If, for example, I pass 10 spaces (character width 3 pixels) I get the correct value of 40 returned. (3 pixels + 1 pixel padding x 10). However, if I pass 15 spaces I get a width of 47. Similar problems occur with other text strings, some start hitting problems with fewer characters than others, it doesn't seem consistent.

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Wed Aug 14, 2013 4:09 pm

I can't build the sample code here. You could try passing by reference in width of string?

blackcattech
Posts: 113
Joined: Mon Jan 11, 2010 10:39 pm
Location: Chesterfield

Post by blackcattech » Thu Aug 15, 2013 7:58 am

Do you mean changing the code so it reads 'ByRef CStr as String' in the function definition?

If I'm understanding that right, I've tried it and the problem there is that I can't pass constant strings that way. String variables OK, but I use the function for both variable and fixed strings.

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Thu Aug 15, 2013 8:09 am

OK, post some code that a can fully build here and I will take a look - keep it as short as possible to show the error...

blackcattech
Posts: 113
Joined: Mon Jan 11, 2010 10:39 pm
Location: Chesterfield

Post by blackcattech » Thu Aug 15, 2013 2:09 pm

Not sure how much code you will need to recreate this. If you are able to do without the output routine and read the returned width elsewhere then this might be enough:

Code: Select all

Public Const MediumFont() As Byte = (
        15, 15, 32, 90,
        $7A, $00,       // Space
        $8B, $00,       // !
        $90, $00,       // "
        $9B, $00,       // #
        $B4, $00,       // $
        $C5, $00,       // %
        $E2, $00,       // &
        $F7, $00,       // '
        $FC, $00,       // (
        $07, $01,       // )
        $12, $01,       // *
        $1F, $01,       // +
        $30, $01,       // ,
        $35, $01,       // -
        $42, $01,       // .
        $47, $01,       // /
        $52, $01,       // 0
        $63, $01,       // 1
        $70, $01,       // 2
        $81, $01,       // 3
        $92, $01,       // 4
        $A3, $01,       // 5
        $B4, $01,       // 6
        $C5, $01,       // 7
        $D6, $01,       // 8
        $E7, $01,       // 9
        $F8, $01,       // :
        $01, $02,       // ;
        $06, $02,       // <
        $17, $02,       // =
        $28, $02,       // >
        $39, $02,       // ?
        $4A, $02,       // Solid arrow (was @
        $59, $02,       // A
        $70, $02,       // B
        $83, $02,       // C
        $98, $02,       // D
        $AD, $02,       // E
        $C0, $02,       // F
        $D3, $02,       // G
        $EA, $02,       // H
        $FF, $02,       // I
        $04, $03,       // J
        $13, $03,       // K
        $28, $03,       // L
        $39, $03,       // M
        $54, $03,       // N
        $69, $03,       // O
        $80, $03,       // P
        $93, $03,       // Q
        $AA, $03,       // R
        $C1, $03,       // S
        $D4, $03,       // T
        $E9, $03,       // U
        $FE, $03,       // V
        $15, $04,       // W
        $34, $04,       // X
        $4B, $04,       // Y
        $64, $04,       // Z
        $08, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,                                                                        ' Code for char  
        $02, $FF, $67, $FF, $67,                                                                                                                                    ' Code for char !
        $05, $1F, $00, $1F, $00, $00, $00, $1F, $00, $1F, $00,                                                                                                      ' Code for char "
        $0C, $00, $06, $30, $76, $B0, $7F, $F8, $1F, $FF, $06, $37, $06, $30, $76, $B0, $7F, $F8, $1F, $FF, $06, $37, $06, $30, $00,                                ' Code for char #
        $08, $3C, $18, $7E, $38, $E7, $70, $C3, $60, $FF, $7F, $83, $61, $8E, $3F, $0C, $1F,                                                                        ' Code for char $
        $0E, $3C, $00, $42, $00, $42, $40, $42, $70, $3C, $3C, $00, $0F, $80, $03, $E0, $00, $78, $00, $1E, $1E, $07, $21, $01, $21, $00, $21, $00, $1E,            ' Code for char %
        $0A, $00, $1E, $00, $3F, $9C, $71, $FF, $60, $E3, $60, $E3, $61, $3F, $37, $1E, $1F, $00, $3B, $00, $20,                                                    ' Code for char &
        $02, $1F, $00, $1F, $00,                                                                                                                                    ' Code for char '
        $05, $E0, $03, $F8, $0F, $1E, $3C, $07, $70, $01, $40,                                                                                                      ' Code for char (
        $05, $01, $40, $07, $70, $1E, $3C, $F8, $0F, $E0, $07,                                                                                                      ' Code for char )
        $06, $06, $00, $34, $00, $1F, $00, $1F, $00, $34, $00, $06, $00,                                                                                            ' Code for char *
        $08, $80, $01, $80, $01, $80, $01, $F0, $0F, $F0, $0F, $80, $01, $80, $01, $80, $01,                                                                        ' Code for char +
        $02, $00, $58, $00, $38,                                                                                                                                    ' Code for char ,
        $06, $80, $01, $80, $01, $80, $01, $80, $01, $80, $01, $80, $01,                                                                                            ' Code for char -
        $02, $00, $30, $00, $30,                                                                                                                                    ' Code for char .
        $05, $00, $38, $80, $3F, $F8, $07, $7F, $00, $07, $00,                                                                                                      ' Code for char /
        $08, $F8, $0F, $FE, $3F, $07, $70, $03, $60, $03, $60, $07, $70, $FE, $3F, $F8, $0F,                                                                        ' Code for char 0
        $06, $00, $00, $30, $00, $18, $00, $0C, $00, $FF, $7F, $FF, $7F,                                                                                            ' Code for char 1
        $08, $0C, $60, $0E, $78, $07, $6C, $03, $66, $03, $63, $C7, $61, $FE, $60, $3C, $60,                                                                        ' Code for char 2
        $08, $0C, $18, $0E, $38, $07, $70, $C3, $60, $C3, $60, $E7, $71, $BE, $3F, $1C, $1F,                                                                        ' Code for char 3
        $08, $00, $07, $C0, $07, $F0, $06, $3C, $06, $0F, $06, $FF, $7F, $FF, $7F, $00, $06,                                                                        ' Code for char 4
        $08, $F0, $18, $FF, $38, $6F, $70, $63, $60, $63, $60, $E3, $70, $C3, $3F, $80, $0F,                                                                        ' Code for char 5
        $08, $F8, $0F, $FE, $3F, $C6, $70, $63, $60, $63, $60, $E7, $70, $CE, $3F, $8C, $1F,                                                                        ' Code for char 6
        $08, $03, $00, $03, $00, $03, $78, $83, $7F, $E3, $07, $7B, $00, $0F, $00, $03, $00,                                                                        ' Code for char 7
        $08, $3C, $1F, $FE, $3F, $E7, $71, $C3, $60, $C3, $60, $E7, $71, $FE, $3F, $3C, $1F,                                                                        ' Code for char 8
        $08, $FC, $18, $FE, $39, $87, $73, $03, $63, $03, $63, $87, $31, $FE, $3F, $F8, $07,                                                                        ' Code for char 9
        $04, $00, $00, $0C, $18, $0C, $18, $00, $00,                                                                                                                ' Code for char :
        $02, $0C, $2C, $0C, $1C,                                                                                                                                    ' Code for char ;
        $08, $C0, $01, $C0, $01, $60, $03, $60, $03, $30, $06, $18, $0C, $18, $0C, $0C, $18,                                                                        ' Code for char <
        $08, $30, $06, $30, $06, $30, $06, $30, $06, $30, $06, $30, $06, $30, $06, $30, $06,                                                                        ' Code for char =
        $08, $0C, $18, $18, $0C, $18, $0C, $30, $06, $60, $03, $60, $03, $C0, $01, $C0, $01,                                                                        ' Code for char >
        $08, $0C, $00, $0E, $00, $07, $00, $03, $6E, $83, $6F, $C7, $01, $FE, $00, $3C, $00,                                                                        ' Code for char ?
        $07, $FE, $3F, $FC, $1F, $F8, $0F, $F0, $07, $E0, $03, $C0, $01, $80, $00,                                                                                  ' Code for char @
        $0B, $00, $60, $00, $7E, $E0, $1F, $FC, $07, $3F, $06, $03, $06, $3F, $06, $FC, $07, $E0, $1F, $00, $7E, $00, $60,                                          ' Code for char A
        $09, $FF, $7F, $FF, $7F, $C3, $60, $C3, $60, $C3, $60, $C3, $60, $E7, $71, $BE, $3F, $1C, $1F,                                                              ' Code for char B
        $0A, $F0, $07, $FC, $1F, $0E, $38, $07, $70, $03, $60, $03, $60, $03, $70, $0E, $38, $1E, $1E, $18, $06,                                                    ' Code for char C
        $0A, $FF, $7F, $FF, $7F, $03, $60, $03, $60, $03, $60, $03, $60, $07, $70, $0E, $38, $FC, $1F, $F0, $07,                                                    ' Code for char D
        $09, $FF, $7F, $FF, $7F, $C3, $60, $C3, $60, $C3, $60, $C3, $60, $C3, $60, $C3, $60, $C3, $60,                                                              ' Code for char E
        $09, $FF, $7F, $FF, $7F, $C3, $00, $C3, $00, $C3, $00, $C3, $00, $C3, $00, $C3, $00, $03, $00,                                                              ' Code for char F
        $0B, $F0, $07, $FC, $1F, $0E, $38, $06, $30, $03, $60, $03, $60, $83, $61, $83, $61, $86, $31, $9E, $3F, $98, $1F,                                          ' Code for char G
        $0A, $FF, $7F, $FF, $7F, $C0, $00, $C0, $00, $C0, $00, $C0, $00, $C0, $00, $C0, $00, $FF, $7F, $FF, $7F,                                                    ' Code for char H
        $02, $FF, $7F, $FF, $7F,                                                                                                                                    ' Code for char I
        $07, $00, $1C, $00, $3C, $00, $70, $00, $60, $00, $60, $FF, $3F, $FF, $1F,                                                                                  ' Code for char J
        $0A, $FF, $7F, $FF, $7F, $80, $01, $E0, $00, $F0, $01, $98, $07, $0C, $0E, $07, $38, $03, $70, $00, $40,                                                    ' Code for char K
        $08, $FF, $7F, $FF, $7F, $00, $60, $00, $60, $00, $60, $00, $60, $00, $60, $00, $60,                                                                        ' Code for char L
        $0D, $FF, $7F, $FF, $7F, $3F, $00, $FC, $01, $C0, $1F, $00, $7E, $00, $60, $00, $7E, $C0, $1F, $F8, $03, $3F, $00, $FF, $7F, $FF, $7F,                      ' Code for char M
        $0A, $FF, $7F, $FF, $7F, $1E, $00, $78, $00, $E0, $01, $C0, $03, $00, $0F, $00, $3C, $FF, $7F, $FF, $7F,                                                    ' Code for char N
        $0B, $F0, $07, $FC, $1F, $0E, $38, $07, $70, $03, $60, $03, $60, $03, $60, $07, $70, $0E, $38, $FC, $1F, $F0, $07,                                          ' Code for char O
        $09, $FF, $7F, $FF, $7F, $83, $01, $83, $01, $83, $01, $83, $01, $C7, $01, $FE, $00, $7C, $00,                                                              ' Code for char P
        $0B, $F0, $07, $FC, $1F, $0E, $38, $07, $70, $03, $60, $03, $60, $03, $68, $07, $30, $0E, $38, $FC, $6F, $F0, $43,                                          ' Code for char Q
        $0B, $FF, $7F, $FF, $7F, $C3, $00, $C3, $00, $C3, $00, $C3, $01, $43, $03, $67, $0E, $7E, $3C, $3C, $70, $00, $40,                                          ' Code for char R
        $09, $3C, $18, $7E, $38, $67, $70, $C3, $60, $C3, $60, $83, $61, $87, $73, $0E, $3F, $0C, $1E,                                                              ' Code for char S
        $0A, $03, $00, $03, $00, $03, $00, $03, $00, $FF, $7F, $FF, $7F, $03, $00, $03, $00, $03, $00, $03, $00,                                                    ' Code for char T
        $0A, $FF, $0F, $FF, $3F, $00, $70, $00, $60, $00, $60, $00, $60, $00, $60, $00, $30, $FF, $3F, $FF, $0F,                                                    ' Code for char U
        $0B, $03, $00, $3F, $00, $FC, $01, $C0, $1F, $00, $7E, $00, $60, $00, $7E, $C0, $1F, $FC, $01, $3F, $00, $03, $00,                                          ' Code for char V
        $0F, $07, $00, $FF, $00, $F8, $1F, $00, $7F, $00, $60, $F8, $7F, $FF, $0F, $03, $00, $FF, $0F, $F8, $7F, $00, $60, $00, $7F, $F8, $1F, $FF, $00, $0F, $00,  ' Code for char W
        $0B, $01, $40, $07, $70, $0E, $38, $3C, $1E, $F0, $07, $C0, $01, $F0, $07, $3C, $1E, $0E, $38, $03, $70, $01, $40,                                          ' Code for char X
        $0C, $01, $00, $07, $00, $0E, $00, $3C, $00, $F0, $00, $C0, $7F, $C0, $7F, $F0, $00, $38, $00, $0E, $00, $07, $00, $01, $00,                                ' Code for char Y
        $0A, $03, $70, $03, $78, $03, $6E, $03, $67, $83, $63, $E3, $60, $73, $60, $1B, $60, $0F, $60, $07, $60                                                     ' Code for char Z
        )

Code: Select all

#option DISPLAY_COLUMNS = 128

Const D_COLUMNS = DISPLAY_COLUMNS

Const FontOffset = 4                // (Size of the header)

    // Find the width of a character. Right hand padding defaults to 1 if not specified.
    // Remember if using this to supply a fixed width to WriteChar or WriteStr that you need to specify zero padding either here or in the write command.
Public Function WidthOfChar(ByRefConst FontMap() As Byte, CNo As Byte, CPad As Byte = 1) As Byte
  Dim w, l As Word

  If CNo < FontMap(2) Then CNo = FontMap(2) EndIf                   // Set limits on the character number.
  IfCNo > FontMap(3) Then CNo = FontMap(3) EndIf                   // Limit to the number of characters defined.  
  CNo = CNo - FontMap(2)                                            // Remove ASCII offset. We will end up with a character reference between 0 and the number of chrs defined.

  w = CNo * 2
  w = w + FontOffset 
  l.byte0 = FontMap(w)
  l.byte1 = FontMap(w+1)
  
  result = FontMap(l) + CPad
End Function

    // Find the width of a full string of characters
Public Function WidthOfStr(ByRefConst FontMap() As Byte, CStr As String) As Byte
  Dim sw, sl As Byte
  
  sw = 0
  sl = 0
  While CStr(sl) <> null
    sw = sw + WidthOfChar(FontMap, CStr(sl))
    Inc(sl)
  Wend
  
  result = sw  
End Function

Public Sub CentralStr(ByRefConst Fontmap() As Byte, CStr As String, YPage As Byte)
  Dim w As Byte
  
  w = D_COLUMNS - WidthOfStr(FontMap, CStr)
  w = w / 2
  // Add code to output width w here
  //WriteStr(Fontmap, CStr, w, YPage)
End Sub

Code: Select all

// Samples of how this routine is called
CentralStr(MediumFont,"01234567890",0)
CentralStr(MediumFont,"ABCDEFGHIJK",0)
CentralStr(MediumFont,"               ",0)

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Thu Aug 15, 2013 2:17 pm

Just to be sure, this code will reproduce the error? Can you put in the code (a) expected result and (b) actual result against each test condition, so that I have some terms of reference. For example,

Code: Select all

' expected = xx, actual = yy
CentralStr(MediumFont,"01234567890",0)
and so on

> If you are able to do without the output routine
> and read the returned width elsewhere

No, I need a way in your code that displays the output.

blackcattech
Posts: 113
Joined: Mon Jan 11, 2010 10:39 pm
Location: Chesterfield

Post by blackcattech » Thu Aug 15, 2013 3:25 pm

I'll have to have a think and see what I can come up with. I have no easily replicable output means, I'm using an OLED on custom hardware for text display so pasting the output routines I use would be of little use to you here. I also don't have an RS232 input so I can't use a terminal instead....

A shame Swordfish doesn't directly support in-circuit debugging.

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

Post by Jerry Messina » Thu Aug 15, 2013 4:57 pm

A shame Swordfish doesn't directly support in-circuit debugging.
While you can't do it directly from the SF IDE, it's pretty easy to use MPLAB and either the MPLAB simulator (if you're only interested in algorithm debugging) or one of the ICD programmers like the Pickit2 or Pickit3 to do actual in-circuit source level debugging.

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

Post by Jerry Messina » Thu Aug 15, 2013 6:37 pm

It seems that the length allocation for the CStr parameter in WidthOfStr() isn't consistent.

I used four different length strings for the test (all spaces). I tried a few different test cases, and depending on the order in which I declared the calls I got different allocation lengths for CStr. Depending on the order of the test calls, other variables can/are getting stomped on.

BTW - for the given MediumFont, a SPACE character should end up 8 pixels wide + 1 = 9 pixels/char

Code: Select all

Test #1
----------
CentralStr(MediumFont,"          ", 0)      		// w = 10*9=90
CentralStr(MediumFont,"                    ", 0)    // w = 20*9=180
CentralStr(MediumFont,"               ", 0)      	// w = 15*9=135
CentralStr(MediumFont,"          ", 0)      		// w = 90


   .func PUB 00003 $005B6 00086 $002B 0021 00162 00170 WidthOfStr
   .var CEF $002B 00 0000 0000 U08    FontMap
   .var VAL $002F 00 0011 0000 U08    CStr         <<<<<<<<<<<<
   .var PRI $003A 00 0000 0000 U08    sw
   .var PRI $003B 00 0000 0000 U08    sl
   .ret PRI $003C 00 0000 0000 U08    WidthOfStr
   .end
   .proc PUB 00004 $0060C 00048 $0040 0031 00175 00180 CentralStr
   .var CEF $0040 00 0000 0000 U08    Fontmap
   .var VAL $0044 00 0021 0000 U08    CStr
   .var PRI $005A 00 0000 0000 U08    w
   .end


Test #2
----------
CentralStr(MediumFont,"                    ", 0)    // w = 20*9=180
CentralStr(MediumFont,"          ", 0)      		// w = 10*9=90
CentralStr(MediumFont,"               ", 0)      	// w = 15*9=135
CentralStr(MediumFont,"          ", 0)      		// w = 90

   .func PUB 00003 $005B6 00086 $002B 0031 00162 00170 WidthOfStr
   .var CEF $002B 00 0000 0000 U08    FontMap
   .var VAL $002F 00 0021 0000 U08    CStr     <<<<<<<<<<<<
   .var PRI $0044 00 0000 0000 U08    sw
   .var PRI $0045 00 0000 0000 U08    sl
   .ret PRI $0046 00 0000 0000 U08    WidthOfStr
   .end
   .proc PUB 00004 $0060C 00048 $004A 0031 00175 00180 CentralStr
   .var CEF $004A 00 0000 0000 U08    Fontmap
   .var VAL $004E 00 0021 0000 U08    CStr
   .var PRI $0064 00 0000 0000 U08    w
   .end


Test #3
-----------
CentralStr(MediumFont,"               ", 0)      	// w = 15*9=135
CentralStr(MediumFont,"                    ", 0)    // w = 20*9=180
CentralStr(MediumFont,"          ", 0)      		// w = 10*9=90
CentralStr(MediumFont,"          ", 0)      		// w = 90

   .func PUB 00003 $005B6 00086 $002B 0026 00162 00170 WidthOfStr
   .var CEF $002B 00 0000 0000 U08    FontMap
   .var VAL $002F 00 0016 0000 U08    CStr      <<<<<<<<<<<<<
   .var PRI $003F 00 0000 0000 U08    sw
   .var PRI $0040 00 0000 0000 U08    sl
   .ret PRI $0041 00 0000 0000 U08    WidthOfStr
   .end
   .proc PUB 00004 $0060C 00048 $0045 0031 00175 00180 CentralStr
   .var CEF $0045 00 0000 0000 U08    Fontmap
   .var VAL $0049 00 0021 0000 U08    CStr
   .var PRI $005F 00 0000 0000 U08    w
   .end

In case I changed anything while I was looking at it, this is the basic code I used

Code: Select all

#option _showvar = true

public const MediumFont() as byte = (
        15, 15, 32, 90,             // header 0-3
        $7A, $00,       // Space    '4-5
        $8B, $00,       // !
        $90, $00,       // "
        $9B, $00,       // #
        $B4, $00,       // $
        $C5, $00,       // %
        $E2, $00,       // &
        $F7, $00,       // '
        $FC, $00,       // (
        $07, $01,       // )
        $12, $01,       // *
        $1F, $01,       // +
        $30, $01,       // ,
        $35, $01,       // -
        $42, $01,       // .
        $47, $01,       // /
        $52, $01,       // 0
        $63, $01,       // 1
        $70, $01,       // 2
        $81, $01,       // 3
        $92, $01,       // 4
        $A3, $01,       // 5
        $B4, $01,       // 6
        $C5, $01,       // 7
        $D6, $01,       // 8
        $E7, $01,       // 9
        $F8, $01,       // :
        $01, $02,       // ;
        $06, $02,       // <
        $17, $02,       // =
        $28, $02,       // >
        $39, $02,       // ?
        $4A, $02,       // Solid arrow (was @
        $59, $02,       // A
        $70, $02,       // B
        $83, $02,       // C
        $98, $02,       // D
        $AD, $02,       // E
        $C0, $02,       // F
        $D3, $02,       // G
        $EA, $02,       // H
        $FF, $02,       // I
        $04, $03,       // J
        $13, $03,       // K
        $28, $03,       // L
        $39, $03,       // M
        $54, $03,       // N
        $69, $03,       // O
        $80, $03,       // P
        $93, $03,       // Q
        $AA, $03,       // R
        $C1, $03,       // S
        $D4, $03,       // T
        $E9, $03,       // U
        $FE, $03,       // V
        $15, $04,       // W
        $34, $04,       // X
        $4B, $04,       // Y
        $64, $04,       // Z
// offset 122
        $08, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,                                                                        ' Code for char 
        $02, $FF, $67, $FF, $67,                                                                                                                                    ' Code for char !
        $05, $1F, $00, $1F, $00, $00, $00, $1F, $00, $1F, $00,                                                                                                      ' Code for char "
        $0C, $00, $06, $30, $76, $B0, $7F, $F8, $1F, $FF, $06, $37, $06, $30, $76, $B0, $7F, $F8, $1F, $FF, $06, $37, $06, $30, $00,                                ' Code for char #
        $08, $3C, $18, $7E, $38, $E7, $70, $C3, $60, $FF, $7F, $83, $61, $8E, $3F, $0C, $1F,                                                                        ' Code for char $
        $0E, $3C, $00, $42, $00, $42, $40, $42, $70, $3C, $3C, $00, $0F, $80, $03, $E0, $00, $78, $00, $1E, $1E, $07, $21, $01, $21, $00, $21, $00, $1E,            ' Code for char %
        $0A, $00, $1E, $00, $3F, $9C, $71, $FF, $60, $E3, $60, $E3, $61, $3F, $37, $1E, $1F, $00, $3B, $00, $20,                                                    ' Code for char &
        $02, $1F, $00, $1F, $00,                                                                                                                                    ' Code for char '
        $05, $E0, $03, $F8, $0F, $1E, $3C, $07, $70, $01, $40,                                                                                                      ' Code for char (
        $05, $01, $40, $07, $70, $1E, $3C, $F8, $0F, $E0, $07,                                                                                                      ' Code for char )
        $06, $06, $00, $34, $00, $1F, $00, $1F, $00, $34, $00, $06, $00,                                                                                            ' Code for char *
        $08, $80, $01, $80, $01, $80, $01, $F0, $0F, $F0, $0F, $80, $01, $80, $01, $80, $01,                                                                        ' Code for char +
        $02, $00, $58, $00, $38,                                                                                                                                    ' Code for char ,
        $06, $80, $01, $80, $01, $80, $01, $80, $01, $80, $01, $80, $01,                                                                                            ' Code for char -
        $02, $00, $30, $00, $30,                                                                                                                                    ' Code for char .
        $05, $00, $38, $80, $3F, $F8, $07, $7F, $00, $07, $00,                                                                                                      ' Code for char /
        $08, $F8, $0F, $FE, $3F, $07, $70, $03, $60, $03, $60, $07, $70, $FE, $3F, $F8, $0F,                                                                        ' Code for char 0
        $06, $00, $00, $30, $00, $18, $00, $0C, $00, $FF, $7F, $FF, $7F,                                                                                            ' Code for char 1
        $08, $0C, $60, $0E, $78, $07, $6C, $03, $66, $03, $63, $C7, $61, $FE, $60, $3C, $60,                                                                        ' Code for char 2
        $08, $0C, $18, $0E, $38, $07, $70, $C3, $60, $C3, $60, $E7, $71, $BE, $3F, $1C, $1F,                                                                        ' Code for char 3
        $08, $00, $07, $C0, $07, $F0, $06, $3C, $06, $0F, $06, $FF, $7F, $FF, $7F, $00, $06,                                                                        ' Code for char 4
        $08, $F0, $18, $FF, $38, $6F, $70, $63, $60, $63, $60, $E3, $70, $C3, $3F, $80, $0F,                                                                        ' Code for char 5
        $08, $F8, $0F, $FE, $3F, $C6, $70, $63, $60, $63, $60, $E7, $70, $CE, $3F, $8C, $1F,                                                                        ' Code for char 6
        $08, $03, $00, $03, $00, $03, $78, $83, $7F, $E3, $07, $7B, $00, $0F, $00, $03, $00,                                                                        ' Code for char 7
        $08, $3C, $1F, $FE, $3F, $E7, $71, $C3, $60, $C3, $60, $E7, $71, $FE, $3F, $3C, $1F,                                                                        ' Code for char 8
        $08, $FC, $18, $FE, $39, $87, $73, $03, $63, $03, $63, $87, $31, $FE, $3F, $F8, $07,                                                                        ' Code for char 9
        $04, $00, $00, $0C, $18, $0C, $18, $00, $00,                                                                                                                ' Code for char :
        $02, $0C, $2C, $0C, $1C,                                                                                                                                    ' Code for char ;
        $08, $C0, $01, $C0, $01, $60, $03, $60, $03, $30, $06, $18, $0C, $18, $0C, $0C, $18,                                                                        ' Code for char <
        $08, $30, $06, $30, $06, $30, $06, $30, $06, $30, $06, $30, $06, $30, $06, $30, $06,                                                                        ' Code for char =
        $08, $0C, $18, $18, $0C, $18, $0C, $30, $06, $60, $03, $60, $03, $C0, $01, $C0, $01,                                                                        ' Code for char >
        $08, $0C, $00, $0E, $00, $07, $00, $03, $6E, $83, $6F, $C7, $01, $FE, $00, $3C, $00,                                                                        ' Code for char ?
        $07, $FE, $3F, $FC, $1F, $F8, $0F, $F0, $07, $E0, $03, $C0, $01, $80, $00,                                                                                  ' Code for char @
        $0B, $00, $60, $00, $7E, $E0, $1F, $FC, $07, $3F, $06, $03, $06, $3F, $06, $FC, $07, $E0, $1F, $00, $7E, $00, $60,                                          ' Code for char A
        $09, $FF, $7F, $FF, $7F, $C3, $60, $C3, $60, $C3, $60, $C3, $60, $E7, $71, $BE, $3F, $1C, $1F,                                                              ' Code for char B
        $0A, $F0, $07, $FC, $1F, $0E, $38, $07, $70, $03, $60, $03, $60, $03, $70, $0E, $38, $1E, $1E, $18, $06,                                                    ' Code for char C
        $0A, $FF, $7F, $FF, $7F, $03, $60, $03, $60, $03, $60, $03, $60, $07, $70, $0E, $38, $FC, $1F, $F0, $07,                                                    ' Code for char D
        $09, $FF, $7F, $FF, $7F, $C3, $60, $C3, $60, $C3, $60, $C3, $60, $C3, $60, $C3, $60, $C3, $60,                                                              ' Code for char E
        $09, $FF, $7F, $FF, $7F, $C3, $00, $C3, $00, $C3, $00, $C3, $00, $C3, $00, $C3, $00, $03, $00,                                                              ' Code for char F
        $0B, $F0, $07, $FC, $1F, $0E, $38, $06, $30, $03, $60, $03, $60, $83, $61, $83, $61, $86, $31, $9E, $3F, $98, $1F,                                          ' Code for char G
        $0A, $FF, $7F, $FF, $7F, $C0, $00, $C0, $00, $C0, $00, $C0, $00, $C0, $00, $C0, $00, $FF, $7F, $FF, $7F,                                                    ' Code for char H
        $02, $FF, $7F, $FF, $7F,                                                                                                                                    ' Code for char I
        $07, $00, $1C, $00, $3C, $00, $70, $00, $60, $00, $60, $FF, $3F, $FF, $1F,                                                                                  ' Code for char J
        $0A, $FF, $7F, $FF, $7F, $80, $01, $E0, $00, $F0, $01, $98, $07, $0C, $0E, $07, $38, $03, $70, $00, $40,                                                    ' Code for char K
        $08, $FF, $7F, $FF, $7F, $00, $60, $00, $60, $00, $60, $00, $60, $00, $60, $00, $60,                                                                        ' Code for char L
        $0D, $FF, $7F, $FF, $7F, $3F, $00, $FC, $01, $C0, $1F, $00, $7E, $00, $60, $00, $7E, $C0, $1F, $F8, $03, $3F, $00, $FF, $7F, $FF, $7F,                      ' Code for char M
        $0A, $FF, $7F, $FF, $7F, $1E, $00, $78, $00, $E0, $01, $C0, $03, $00, $0F, $00, $3C, $FF, $7F, $FF, $7F,                                                    ' Code for char N
        $0B, $F0, $07, $FC, $1F, $0E, $38, $07, $70, $03, $60, $03, $60, $03, $60, $07, $70, $0E, $38, $FC, $1F, $F0, $07,                                          ' Code for char O
        $09, $FF, $7F, $FF, $7F, $83, $01, $83, $01, $83, $01, $83, $01, $C7, $01, $FE, $00, $7C, $00,                                                              ' Code for char P
        $0B, $F0, $07, $FC, $1F, $0E, $38, $07, $70, $03, $60, $03, $60, $03, $68, $07, $30, $0E, $38, $FC, $6F, $F0, $43,                                          ' Code for char Q
        $0B, $FF, $7F, $FF, $7F, $C3, $00, $C3, $00, $C3, $00, $C3, $01, $43, $03, $67, $0E, $7E, $3C, $3C, $70, $00, $40,                                          ' Code for char R
        $09, $3C, $18, $7E, $38, $67, $70, $C3, $60, $C3, $60, $83, $61, $87, $73, $0E, $3F, $0C, $1E,                                                              ' Code for char S
        $0A, $03, $00, $03, $00, $03, $00, $03, $00, $FF, $7F, $FF, $7F, $03, $00, $03, $00, $03, $00, $03, $00,                                                    ' Code for char T
        $0A, $FF, $0F, $FF, $3F, $00, $70, $00, $60, $00, $60, $00, $60, $00, $60, $00, $30, $FF, $3F, $FF, $0F,                                                    ' Code for char U
        $0B, $03, $00, $3F, $00, $FC, $01, $C0, $1F, $00, $7E, $00, $60, $00, $7E, $C0, $1F, $FC, $01, $3F, $00, $03, $00,                                          ' Code for char V
        $0F, $07, $00, $FF, $00, $F8, $1F, $00, $7F, $00, $60, $F8, $7F, $FF, $0F, $03, $00, $FF, $0F, $F8, $7F, $00, $60, $00, $7F, $F8, $1F, $FF, $00, $0F, $00,  ' Code for char W
        $0B, $01, $40, $07, $70, $0E, $38, $3C, $1E, $F0, $07, $C0, $01, $F0, $07, $3C, $1E, $0E, $38, $03, $70, $01, $40,                                          ' Code for char X
        $0C, $01, $00, $07, $00, $0E, $00, $3C, $00, $F0, $00, $C0, $7F, $C0, $7F, $F0, $00, $38, $00, $0E, $00, $07, $00, $01, $00,                                ' Code for char Y
        $0A, $03, $70, $03, $78, $03, $6E, $03, $67, $83, $63, $E3, $60, $73, $60, $1B, $60, $0F, $60, $07, $60                                                     ' Code for char Z
        )
        
#option DISPLAY_COLUMNS = 128

const D_COLUMNS = DISPLAY_COLUMNS

const FontOffset = 4                // (Size of the header)

    // Find the width of a character. Right hand padding defaults to 1 if not specified.
    // Remember if using this to supply a fixed width to WriteChar or WriteStr that you need to specify zero padding either here or in the write command.
public function WidthOfChar(byrefconst FontMap() as byte, CNo as byte, CPad as byte = 1) as byte
  dim w, l as word

  if CNo < FontMap(2) then CNo = FontMap(2) endif                   // Set limits on the character number.
  if CNo > FontMap(3) then CNo = FontMap(3) endif                   // Limit to the number of characters defined. 
  CNo = CNo - FontMap(2)                                            // Remove ASCII offset. We will end up with a character reference between 0 and the number of chrs defined.

  w = CNo * 2
  w = w + FontOffset
  l.byte0 = FontMap(w)
  l.byte1 = FontMap(w+1)
 
  result = FontMap(l) + CPad
end function

    // Find the width of a full string of characters
public function WidthOfStr(byrefconst FontMap() as byte, CStr as string) as byte
  dim sw, sl as byte
 
  sw = 0
  sl = 0
  while CStr(sl) <> null
    sw = sw + WidthOfChar(FontMap, CStr(sl))
    inc(sl)
  wend
 
  result = sw 
end function

public sub CentralStr(byrefconst Fontmap() as byte, CStr as string, YPage as byte)
  dim w as byte
 
  w = WidthOfStr(FontMap, CStr)
  // set a brkpoint here and examine w before doing other math on it

  w = D_COLUMNS - w
  w = w / 2

  // Add code to output width w here
  //WriteStr(Fontmap, CStr, w, YPage)
end sub


// Samples of how this routine is called
CentralStr(MediumFont,"               ", 0)      // w = 15*9=135
CentralStr(MediumFont,"                    ", 0)      // w = 20*9=180
CentralStr(MediumFont,"          ", 0)      // w = 10*9=90
CentralStr(MediumFont,"          ", 0)      // w = 90


CentralStr(MediumFont,"01234567890",0)
CentralStr(MediumFont,"ABCDEFGHIJK",0)
CentralStr(MediumFont,"               ",0) 

blackcattech
Posts: 113
Joined: Mon Jan 11, 2010 10:39 pm
Location: Chesterfield

Post by blackcattech » Fri Aug 16, 2013 2:15 pm

Thanks, Jerry.

I will have to look in to using MPLAB but I was a bit put off using that as last time I tried I ended up bricking my PICKit3 and had a right hassle fixing it.

If I'm understanding your results correctly, it appears the compiler is looking at the first call of a routine to determine the amount of string space it needs to allow.

Without looking at my code in great detail I think this doesn't apply when you call a routine directly - I use WidthOfStr elsewhere for formatting purposes and it all seems to work as expected.

Presumably the problem comes where a string is being 'passed on' - I guess it is harder under those circumstances to determine the maximum size.

I guess a work-around is to copy the WidthOfStr code in to the CentralStr routine so you don't need to pass the string on. This would also seem to be more RAM efficient - I ended up replacing the CentralStr command by copying and pasting the code each time I used it (only 6 places at the moment) and ended up saving about 35 bytes of RAM.

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

Post by Jerry Messina » Fri Aug 16, 2013 4:04 pm

Without looking at my code in great detail I think this doesn't apply when you call a routine directly - I use WidthOfStr elsewhere for formatting purposes and it all seems to work as expected.

Presumably the problem comes where a string is being 'passed on' - I guess it is harder under those circumstances to determine the maximum size.
That looks to be what's happening.

I added a few direct calls to WidthOfStr() before calling CentralStr() and it was able to determine the proper max length required.

Code: Select all

WidthOfStr(MediumFont,"               ")      // len = 15
WidthOfStr(MediumFont,"                    ")      // len = 20
WidthOfStr(MediumFont,"                              ")      // len = 30
That ended up reserving 31 bytes for Cstr, so all the CentralStr() calls after that were ok (30 bytes + null char)

You can see this if you look in the resulting .IDF file...

Code: Select all

   .func PUB 00002 $005D6 00086 $002B 0041 00153 00161 WidthOfStr
   .var CEF $002B 00 0000 0000 U08    FontMap
   .var VAL $002F 00 0031 0000 U08    CStr           <<<<< reserve 31 bytes
   .var PRI $004E 00 0000 0000 U08    sw
   .var PRI $004F 00 0000 0000 U08    sl
   .ret PRI $0050 00 0000 0000 U08    WidthOfStr
   .end
A workaround might be to add a direct call to WidthOfStr() with the max length string you intend to use.

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

Post by Jerry Messina » Fri Aug 16, 2013 4:37 pm

Oh, and forgot to mention...
I will have to look in to using MPLAB but I was a bit put off using that as last time I tried I ended up bricking my PICKit3 and had a right hassle fixing it.
I've had that happen to me a few times, too.

Whenever you change processor family types like switching from an 18F to a 18FJ, MPLAB will want to download new firmware to the Pickit3.
It also usually does this if you update MPLAB versions, too.

I haven't had any issues of late, but I always follow these steps whenever I switch uC types:

- First off, make sure you've got the most recent version of MPLAB (early versions were more problematic).
- Close MPLAB (if it's open)
- Remove the Pickit3 connection to the target board
- Open MPLAB and change the processor type in MPLAB using "Configure | Select Device..."
(this will give you the "downloading new bootloader, RS, AP, etc")
- After it's all done, save the workspace so the next time it reopens MPLAB with the new setup
- Reconnect the Pickit3 to the new target

I don't know if all of these steps are actually required, but ever since I started being completely paraniod
and doing that whenever I change families things have been pretty stable (knock on wood).

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Sun Aug 18, 2013 8:49 am

Jerry

Thanks for the additional information, it gives me something to look into. I'll try and get a fix ASAP.

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Mon Aug 26, 2013 10:06 am

I've posted an update 2.2.1.8 which should fix the string allocation problem. You can access the download from HELP...ABOUT.

Post Reply