Progmem functions, pgm_read_float and pgm_read_ptr

For some reason I thought that pgm_read_float didn’t exist,
but I just discovered that it apparently does exist.

So to help others, here’s a brief list of some of the available progmem functions and the type that they return:

pgm_read_byte(address) -> uint8_t (unsigned char)
pgm_read_word(address) -> uint16_t (unsigned int)
pgm_read_dword(address) -> uint32_t (unsigned long int)
pgm_read_float(address) -> float
pgm_read_ptr(address) -> void *

For those who are technically inclined,
there’s more useful progmem functions documented here.


Note that this API was intended to be used with C rather than C++, so while this:

const uint16_t * ptr = pgm_read_ptr(someAddress);

is valid C, it’s not valid C++, for the same reason that this isn’t:

T * ptr = malloc(sizeof(T));

because in C++ void * is not implicitly convertible to other pointers for safety reasons.


To circumvent this issue, you can use the following template function:

template<typename T> T * pgm_read_pointer(T * const * pointer)
{
	return reinterpret_cast<T *>(pgm_read_ptr(pointer));
}

Here’s an example use case with string tables:

const char string0[] PROGMEM = "Play Game";
const char string1[] PROGMEM = "Options";

const char * const strings[] PROGMEM =
{
	string0,
	string1,
};

void drawMenu(void)
{
	for(uint8_t i = 0; i < 2; ++i)
	{
		const char * string = pgm_read_pointer(&strings[i]);
		// Draw the string
	}
}

Note that this is also type safe:

const char string0[] PROGMEM = "Play Game";
const char string1[] PROGMEM = "Options";

const char * const strings[] PROGMEM =
{
	string0,
	string1,
};

void badFunction(void)
{
	// Error, type mismatch between const char * and const int *
	const int * string = pgm_read_pointer(&strings[i]);
}
5 Likes

Nicely documented …

2 Likes