Sticking a number in an array of pointers?

Go To Last Post
16 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"It's plot exposition. It has to go somewhere."

I have arrays of pointers I plan to pass to a function. I also need one more value, always a constant, so I just figured I'd stick it on the front of the array. It's information about the stuff the pointers are pointing to.

const __flash uint8_t * Tahoma16[] = {
	16,
	Tahoma16_0,
	Tahoma16_1,
	Tahoma16_2,

And obviously, this will give a warning because "16" is clearly not a pointer to something in memory.

So, I figure, rather naively, to cast the 16 to such a pointer:

const __flash uint8_t * Tahoma16[] = {
        (uint8_t *) 16,
        Tahoma16_0,
        Tahoma16_1,
        ... and so on

But the compiler likes this even less.

Maybe I should make another of the things it points to that says 16?

const __flash uint8_t Tahoma16_size[] = {16};
const __flash uint8_t * Tahoma16[] = {
    Tahoma16_size,
    Tahoma16_0,
    Tahoma16_1,
    bla bla bla

The idea here:
Using the GLCD font creator program gets you a big array of bytes, x bytes per character in the font. You get x bytes for each character, but almost all the characters are smaller (for a porportional font) and don't use most of the x bytes. So I made an array for each character, and a second array of pointers to these arrays. If the average character takes more than 2 bytes less than the biggest character, the result will take up less flash.

For "Tahoma 12pt," which is 16px tall, the GLCD data takes 31 bytes * 96 characters is 2976 bytes. When I'm done rearranging the bits, it seems to take 1738 bytes, counting the extra array of pointers.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Torby wrote:

const __flash uint8_t * Tahoma16[] = {
        (uint8_t *) 16,


But those two pointer types are different!

Once you get the syntax right, what you are trying to do will work, but it should also get you fired. :D

Pass a pointer to the constant int, or declare and pass an object that has an int followed by a single pointer to an array of pointers.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Usually if you've got "connected things" that you want to pass round together you'd combine them in a struct - it'll be much more readable and maintainable and the syntax will actually be simpler. Just put the int and the array together in a single typedef then instantiate one of these with the __flash attribute.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, that actually was my first inclination, but I seem to spend most of my time trying to beat this language into submission and finially give in to whatever it allows me to do.

typedef struct FontData{
	int PxHigh ;
	uint8_t * PxData[] ;
	} FontData;
extern const __flash FontData Tahoma16;
const __flash uint8_t Tahoma16_0[] = {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};// Code for char
const __flash uint8_t Tahoma16_1[] = {2, 21, 85, 81, 64};// Code for char !
const __flash uint8_t Tahoma16_2[] = {5, 74, 82, 148, 128, 0, 0, 0, 0, 0, 0};// Code for char "
const __flash uint8_t Tahoma16_3[] = {11, 0, 1, 8, 33, 8, 71, 254, 33, 4, 33, 8, 33, 31, 248, 132, 33, 4, 32, 0, 0, 0, 0};// Code for char #

const __flash FontData Tahoma16 = { .PxHigh=16, .PxData={
	Tahoma16_0,
	Tahoma16_1,
	Tahoma16_2,
	Tahoma16_3,
         .. 96 of them
}

But it errors on every line of the array data saying, "initializer element is not computable at load time."

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Torby wrote:
But it errors on every line of the array data saying, "initializer element is not computable at load time."
And what does it say when you change
uint8_t * PxData[] ;

into

const __flash uint8_t * PxData[]; 

?

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Don't take my word for it, but I've never seen anything like this before:
.PxHigh=16, .PxData

One of the things about using structures, as far as I know(I won't keep saying this, take it as read that I know very little more than you do, but I have just been adding a font to a project) is that the size of a structure is fixed. Therefore, if you want to have characters which vary in the number of bytes they consume, you really need a list of offsets into a large array of bytes. You can still keep such things as the character width with the bytes that define the character, if you wish(I am doing so).
In my case, my font structure is defined like this.

// Define a font structure
typedef struct fontstruct
	{
	uint32_t width;				// Max width of character
	uint32_t height;					// Max height of character
	uint32_t chars;					// Number of characters in font
	const uint16_t *offs_tab;		// Pointer to table of offsets into font bitmap
	const uint8_t *bitmap;			// Pointer to start of font bitmap
}font;

The table of offsets into the bitmap info looks like this:

const uint16_t courB24_offs_tab[] =
{
	0x0000,	//Offset to char  32, 0x20
	0x0006,	//Offset to char  33, 0x21
	0x001b,	//Offset to char  34, 0x22
	0x0027,	//Offset to char  35, 0x23
	0x0052,	//Offset to char  36, 0x24
	0x007f,	//Offset to char  37, 0x25
	0x00a2,	//Offset to char  38, 0x26
etc.

and the bitmap info itself looks like this:

	//  32 0x20 space at offset 0000
//	width	bbx	bby	bbw	bbh
		8,	0,	18,	1,	1,
	________,
	//  33 0x21 exclam at offset 0006
	//	width	bbx	bby	bbw	bbh
	10,	5,	3,	4,	16,
	_XX_____,
	XXXX____,
	XXXX____,
	XXXX____,
	XXXX____,
	XXXX____,
	XXXX____,
	XXXX____,
	_XX_____,
	_XX_____,
	_XX_____,
	_XX_____,
	________,
	________,
	_XX_____,
	_XX_____,
	//  34 0x22 quotedbl at offset 001b
	//	width	bbx	bby	bbw	bbh
	12,	3,	4,	8,	7,
	XXX__XXX,
	XXX__XXX,
	XXX__XXX,
	XXX__XXX,
	XX___XX_,
	X____X__,
	X____X__,
	//  35 0x23 numbersign at offset 0027
	//	width	bbx	bby	bbw	bbh
	14,	1,	2,	12,	19,
	____XX__,XX______,
	____XX__,XX______,
	____XX__,XX______,
	____XX__,XX______,
	____XX__,XX______,
	____XX__,XX______,
	_XXXXXXX,XXXX____,
	_XXXXXXX,XXXX____,
	___XX__X,X_______,
	___XX__X,X_______,
	___XX__X,X_______,
	XXXXXXXX,XXX_____,
	XXXXXXXX,XXX_____,
	__XX__XX,________,
	__XX__XX,________,
	__XX__XX,________,
	__XX__XX,________,
	__XX__XX,________,
	__XX__XX,________,

The underscores and Xs are all defined in another header file that looks like this:

	/// #defines to have human readable font files
#define ________ 0x00
#define _______X 0x01
#define ______X_ 0x02
#define ______XX 0x03
#define _____X__ 0x04
#define _____X_X 0x05
#define _____XX_ 0x06
#define _____XXX 0x07
#define ____X___ 0x08
#define ____X__X 0x09
#define ____X_X_ 0x0A
#define ____X_XX 0x0B
#define ____XX__ 0x0C
#define ____XX_X 0x0D
#define ____XXX_ 0x0E
#define ____XXXX 0x0F
#define ___X____ 0x10
#define ___X___X 0x11
#define ___X__X_ 0x12
#define ___X__XX 0x13
#define ___X_X__ 0x14

etc.

and the other bytes before the actual character data control stuff to do with where the character sits within the box, as it were.

Most of this was copied from an open source program called BDF2C, which takes fonts in BDF format and converts them to C useable stuff, although I have heavily modified it all to suit my needs.

I hope this helps.

John

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And now I can't seem to pass my array of pointers to arrays to a function

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Otay. Here's what I have:

typedef struct fontstruct 
    { 
    uint8_t height;               // Max height of character 
    uint8_t chars;               // Number of characters in font 
    const uint16_t *offs_tab;      // Pointer to table of offsets into font bitmap 
    const uint8_t *bitmap;         // Pointer to start of font bitmap 
 }fontstruct;

If I ever have more than 256 characters or they are ever wider then 256 pixels, I'll need something bigger than an avr to run the program.

I built the offset table like so:

const uint16_t Tahoma16_offset[] = {
    0, // Offset to char 0
    17, // Offset to char 1
    22, // Offset to char 2
    -- and so on
};

Since I used a program to generate the source, I skipped the defs needed to make __X and such into 001, and built my bitmap thusly:

const uint8_t Tahoma16_bitmap[]={
8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,21,85,81,64,5,74,82,148,128,0,0,0,0,0,
0,11,0,1,8,33,8,71,254,33,4,33,8,33,31,248,132,33,4,32,0,0,0,0,8,0,8,8,62,73,72,72,
  and so on for a lot of numbers
};

So I can almost build my fontstruct:

const __flash fontstruct Tahoma16={
	16, 
	96, 
	Tahoma16_offset, 
	Tahoma16_bitmap};

I defined my function:

void LCDWriteChar(	int x, int y, 
					char c, const fontstruct font, 
					uint16_t Color, uint16_t Background);

And called it like so:

	LCDWriteChar(112,100,'F',Tahoma16,ColorBlack,ColorWhite);

And the compiler likes it! (How'd that happen?)

Now, C isn't going to want to put all this in preciously short ram, is it? That's why I was using __flash...

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Um, data memory is 1746 bytes, so C is apparently moving all this to ram. So how do I get it all to stay in progmem? Let's play with __flash and see what goes amiss.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, you will need to add some progmem or flash qualifiers to all that to get the tables/bitmaps to reside in flash. The stuff I cut and pasted is from a SAM4 project, so I didn't have to worry about that. Sorry, I forgot about that...
You will obviously need the use PGM_read functions to access the data as well.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If I put __flash on the two arrays, the structure

const __flash fontstruct Tahoma16={
	16, 
	96, 
	Tahoma16_offset, 
	Tahoma16_bitmap};

C complains "initializer element not computable at load time." I try to tell it, "no, you figure this at link time," but, of course, it pays me no attention.

So, to get by for the time being, I made an init function:

void Tahoma16(fontstruct * f)
{
	f->height = 16 ;
	f->chars = 96 ;
	f->offsettable = (uint16_t*) & Tahoma16_offset ;
	f->bitmap = (uint8_t*) & Tahoma16_bitmap ;
};

To get a structure to pass to LCDWriteChar.

This makes the code to use it a bit messier:

	fontstruct t16 ; Tahoma16(&t16);
	LCDWriteChar(112,100,'F',&t16,ColorBlack,ColorWhite);
	LCDWriteChar(112,80, 'A',&t16,ColorBlue,ColorWhite);

Which exposes a dreadful aspect of C If the designers weren't afraid of compiler logic, they'd know the difference between val and var parameters and you'd specify that the function takes a var parameter and the compiler would have put in the extra dereferences itself rather than expecting you to. I say, you embedded engineers suffer terribly of C

I also wonder if I should go to SAM parts for this project.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

Last Edited: Wed. Dec 18, 2013 - 08:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Don't take my word for it, but I've never seen anything like this before:
.PxHigh=16, .PxData

What you are looking at there is a C99 feature called designated initalisers . It's possibly one of the best features of C99 and probably the one I use more than any other which is why it comes as such a disappointment to find that Microsoft Visual C does not support C99.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I did say "Don't take my word for it".

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I saw it on google. "Useful," thought I. Didn't realize it's a new feature.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

new

Does 1999 still count as "new" when we're virtually in 2014?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Microsoft seem to think so.

Four legs good, two legs bad, three legs stable.