Doug- thanks for the link.
Chris-
Most of the examples, like yours, are string examples, and I'm having a hard time relating that to my use case. I have a structure,
typedef struct _SingleDay
{
uint16_t Y;
uint8_t M;
uint8_t D;
BellSched* dayType;
uint8_t dayLetter;
} SingleDay;
and a global array of 180 of these called TheCalendar:
const PROGMEM SingleDay TheCalendar[]=
{
{2018,9,4,NormalDay,'A'},
{2018,9,5,NormalDay,'B'},
{2018,9,6,NormalDay,'C'},
{2018,9,7,NormalDay,'D'},
...
}
The BellSched structure is defined thus:
typedef struct _BellSched
{
uint8_t NumPeriods;
Period Periods[MAX_PERIODS];
} BellSched;
where Period is:
typedef struct _Period
{
uint8_t begH;
uint8_t begM;
uint8_t endH;
uint8_t endM;
uint32_t aCol;
uint32_t bCol;
uint32_t cCol;
uint32_t dCol;
} Period;
So that I can look through the table to find the current day, find the day's letter (A-D), and the day's bell schedule (e.g. NormalDay)
const PROGMEM BellSched NormalDay[]=
{
9,
{ 8, 0, 8,50, OUTOFCLUSTER, RED, OUTOFCLUSTER, YELLOW},
{ 8,52, 9,40, RED, YELLOW, YELLOW, OUTOFCLUSTER},
{ 9,42, 9,52, ASPIRE, ASPIRE, ASPIRE, ASPIRE},
{ 9,54,10,42, YELLOW, OUTOFCLUSTER, RED, RED},
{10,44,11,32, GREEN, OUTOFCLUSTER, BLUE, GREEN},
{11,34,12,23, OUTOFCLUSTER, BLUE, GREEN, PURPLE},
{12,25,12,46, LUNCH, LUNCH, LUNCH, LUNCH},
{12,48,13,36, BLUE, PURPLE, PURPLE, OUTOFCLUSTER},
{13,38,14,26, PURPLE, GREEN, OUTOFCLUSTER, BLUE},
};
I have code that runs when the minute changes to see if we're in a new period:
void DoNewMinuteStuff()
{
currentMinute = now.minute();
if ( dayType == dtWeekend || dayType == dtHoliday || clockType == ctAfterSchool );
else
{
//check against bellschedule, set pointer to current period, and set clock type
BellSched *bs = Today->dayType;
if ( clockType == ctBeforeSchool )
{
// see if we've made it to first period
Period *p = &bs->Periods[0];
if ( now.hour() == p->begH && now.minute() == p->begM )
{
currentPeriod = 0;
clockType = ctDuringClass;
}
}
else
{
Period *p = &bs->Periods[currentPeriod];
if ( currentPeriod < bs->NumPeriods-1 )
{
Period *np = &bs->Periods[currentPeriod+1];
// consider we may have started the next period
if ( isAfterTime(now.hour(), now.minute(), np->begH, np->begM) )
{
clockType = ctDuringClass;
currentPeriod++;
return;
}
}
if ( timeDiff(p->endH, p->endM, now.hour(), now.minute()) < countdownM )
{
clockType = ctEndFlash;
}
else if ( isAfterTime(now.hour(), now.minute(), p->endH, p->endM) )
{
if ( currentPeriod < bs->NumPeriods-1 )
{
clockType = ctPassing;
}
else clockType = ctAfterSchool;
}
}
}
}
So for each field I want to retrieve, do I need to use the pgm_read_ function call? Seems so. But I don't want to have all those calls sprinkled throughout my code. I'd rather hide that complexity, so redefining things as a class, and using a "get" type method for accessing the data, seems the most natural. I believe, for instance, that strcpy_P hides the complexity of reading each byte in pgm space with a function call.