Trying to understand how a series of arrays is being mapped in an AVR routine

56 Views Asked by At

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.

1

There are 1 best solutions below

0
On

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!