I'm trying to port an Arduino AVR routine either to ESP32/8266 or a Python script and would appreciate understanding how to crack the operation of this program. I'm self-teaching and am only looking to get something that works - pretty isn't required. This is a hobby and I am the only audience. The basic operations are understood (99% certain ;)) - there are 4 arrays total: Equilarg
and Nodefactor
contain 10 rows of 37 values; startSecs
contains the epochtime values for the start of each year (2022-2032); and speed
contains 37 values.
I believe each row of the Equilarg
and Nodefactor
arrays corresponds to the year, but I can't work out how the the specific element is pulled from each of the 3, 37 element arrays.
Here is the operating code:
// currentTide calculation function, takes a DateTime object from real time clock.
float TideCalc::currentTide (DateTime now)
{
// Calculate difference between current year and starting year.
YearIndx = now.year() - startYear;
// Calculate hours since start of current year. Hours = seconds / 3600
currHours = (now.unixtime() - pgm_read_dword_near (&startSecs[YearIndx])) / float(3600);
// Shift currHours to Greenwich Mean Time
currHours = currHours + adjustGMT;
// **************Calculate current tide height**********
// initialize results variable, units of feet.
// (This is 3.35 if it matters to understanding how it works)
tideHeight = Datum;
for (int harms = 0; harms < 37; harms++)
{
// Step through each harmonic constituent, extract the relevant
// values of Nodefactor, Amplitude, Equilibrium argument, Kappa
// and Speed.
currNodefactor = pgm_read_float_near (&Nodefactor[YearIndx][harms]);
currAmp = pgm_read_float_near (&Amp[harms]);
currEquilarg = pgm_read_float_near (&Equilarg[YearIndx][harms]);
currKappa = pgm_read_float_near (&Kappa[harms]);
currSpeed = pgm_read_float_near (&Speed[harms]);
// Calculate each component of the overall tide equation
// The currHours value is assumed to be in hours from the start of
// the year, in the Greenwich Mean Time zone, not the local time zone.
tideHeight = tideHeight + currNodefactor * currAmp
* cos ((currSpeed * currHours + currEquilarg - currKappa) * DEG_TO_RAD);
}
//***************End of Tide Height calculation**********
// Output of tideCalc is the tide height, units of feet.
return tideHeight;
}
I've made several attempts to reverse engineer by running the code on an AVR board and trapping the input values and then work backwards but I'm just not seeing a basic part or two. In this instance knowing "kinda" what's going on falls too short.
pgm_read_float_near
reads a float value from flash memory. It needs the address of the value. We give it the address of the indexed value when we use&Amp[harms]
for example. Both Nodefactor and Equilarg are doubly indexed - by year and then by harmonic, while the other three are indexed by the harmonic alone.It sounds like this is a Fourier series curve fit for the tide height. So they're summing up a series of cosine values, each with different amplitude, frequency, and phase.
As @Tom suggests, copy the code to a plain C file, make a little routine for a dummy
pgm_read_float_near
and see how it works on your PC. Many times I write and debug algorithms on a "big" computer, and later plop the code into the Arduino.Have fun!