DotTune AFMA (dot_tune.mo)

Started by Kent, February 20, 2013, 06:17:09 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Kent

An automated version of the Dot-Tune focus tuning method.

Note, this module does not add AFMA support to camera bodies that did not contain this feature in Canon firmware.


QuoteCould this be someting to automate with ML ?

5D3 , EF 100 2.8L Macro, EF 24-105 4L, EF 70-200 2.8L IS, EF 400 5.6L, 580 EX II's, RRS BH-55, Gitzo GT5532LS, Pixel King's, ZOOM H4N

g3gg0

interesting method.
that would be definitely a use case for the picoc scripting API.
"just" need to find out how to set the AF value property and how to get the focus confirmation.
(not sure if the known focus confirmation memory address is working for this use case)
Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

a1ex

Yes, the focus confirmation constant would work here.

PhotoCat

In addition to the automation,  for a single lens, it would be nice for ML to store different AFMA values for different subject distance, since the Canon AFMA implementation is very distance dependent.  Ideally ML would apply a different AFMA value depending on the subject distance reported by the lens :) , if that is possible.

horshack

Hey guys, this is horshack, the guy who did the DotTune YouTube video. My day job happens to be as an embedded firmware engineer so any help you think I can provide just say the word.

I looked over the source of the first commit (https://bitbucket.org/hudson/magic-lantern/commits/6cf3c98700f4b659215d14ede8d6fe15eeca2e81). In the source I see the logic uses a scoring mechanism for each tune value. The scores are 0 to 4, based on a total of 4 iterations executed for each tune value (2 inner loops x 2 outer loops). Each iteration samples 'FOCUS_CONFIRMATION' 20 times, delaying 10ms (or 10us?) between each sample, and increments the score once if any of those 20 samples yields a focus confirmation.

My first question...I assume 'FOCUS_CONFIRMATION' is either a memory-mapped variable/register driven by hardware tied to the PDAF system, or is a global variable set by some background task that is polling the PDAF hardware. If it's the latter, what is the polling frequency of that background task? I ask because broadly speaking, DotTune is biased toward a negative feedback sampling methodology, whereas the ML source implementation can interpreted as either positive or negative feedback sampling, depending on the timing properties of 'FOCUS_CONFIRMATION'. I'm just trying to correlate the user-perceptible VF confirmation feedback with how that same mechanism would be sampled from the ML implementation.

Thanks,

Horshack

a1ex

Wow, thanks for feedback!

FOCUS_CONFIRMATION is a variable in Canon code which becomes TRUE when focus confirmation is achieved. The exact meaning is unknown, but I've noticed that:
- sometimes it becomes TRUE for a short amount of time
- sometimes it stays TRUE for the entire period while focus is confirmed (until I move the camera)

I don't know if these two differences indicate stronger or weaker focus confirmation; at first sight, I didn't notice any correlation.

I've just tweaked the numbers by trial and error, so each focus beep is detected by ML. A few beeps are still missed though (5% or so).

10ms is the timing resolution for DryOS.

Focus confirmation is also sent via GUI events, but these codes are not fully understood yet. If I understand this, there will be no more hit and miss due to polling.

So... back to your question: Canon tasks use event-driven programming for this focus confirmation (so timing is probably variable), but ML uses polling because this is what we know. And one focus beep means one increment in the scoring mechanism. There are 4 passes for better accuracy.

These time-critical events (including PDAF, focus beep, shutter control, lens communication etc) happen in a small microcontroller (Tx19a) that can't be accessed from ML. We can only program the general-purpose CPU (ARM). The ARM receives many of the Tx19a events in order to update the main display and sync camera settings, but with some latency.

Greg

It looks interesting. You can make a preset 3200K and 6500K.  ;)

horshack

Quote from: a1ex on February 22, 2013, 11:35:41 AM
Wow, thanks for feedback!

FOCUS_CONFIRMATION is a variable

Thanks a1ex, that gives me a nice overview of the embedded environment.

Algorithmically, the ML implementation would likely want to match the human-level algorithm of DotTune, provided that the behavior FOCUS_CONFIRMATION roughly matches the behavior of confirmation dot delivered in the VF.

Q: Is msleep() only used as a method to measure time and delay, or is it also required to allow background tasks to execute? (non-preemptive yield point for DryOS). If it's the former, do you have an alternate way to measure elapsed time so that the FOCUS_CONFIRMATION loops can sample continuously without yielding? This would eliminate sampling/timing errors of the variable relative to the micro-controller/background task that updates it.

Q: Is FOCUS_CONFIRMATION updated continuously while the camera is powered on or is there an internal trigger needed to initiate the background task sampling, akin to a half-press of the shutter? I see in your source that you call fake_simple_button(). Is that for this purpose?

Q: It might take some trial and error but I think we'd need to establish roughly what the time delta is between changing an AF tune value and when the first PD sensing result in FOCUS_CONFIRMATION reflects that new value. For the purposes of the source provided below I took a swag at 100ms.

Here is source to an implementation that uses an algorithm that matches the user-level steps of DotTune. Some questions remain about how exactly FOCUS_CONFIRMATION works relative to the VF indication, so this logic may need some tweaks after debugging. Unfortunately I sold my 5DM2 some time ago and the only Canon body I have with me is a 5DM3, which seems to still be in alpha for ML.


#define TUNE_VALUE_INVALID              (INT_MIN)
#define MIN_TUNE_VALUE                  (-20)
#define MAX_TUNE_VALUE                  (20)

#define AF_TUNE_CHANGE_SETTLE_TIME_MS        (100)  // time it takes for PDAF to resample phase after changing AF tune (swag)
#define MAX_TIME_TO_FIRST_FOCUS_CONFIRM_MS   (300)  // max time we allow before 1st focus confirmation (swag)
#define MIN_CONTINUOUS_FOCUS_CONFIRM_TIME_MS (5000) // min time that focus confirmation must remain TRUE

int is_focus_confirmed(void) {
    return FOCUS_CONFIRMATION;
}

int perform_dot_tune(void) { // returns optimal AF tune value or TUNE_VALUE_INVALID

    int tuneValue;
    int confirmedTuneRangeLow, confirmedTuneRangeHigh;
    int waitTimeMs;

    //
    // algorithm: with critical focus already established prior to
    // this routine being called, we scan through the full +/- 20
    // AF tune range to find the range of values which produce
    // an immediate and consistent focus confirmation, then use
    // the midpoint of that confirmed range as the optimal AF tune value.
    //
    // when the scan starts we're looking for the first tune value
    // that produces an immediate and consistent focus confirmation;
    // that represents the low end of the confirmed range. once we
    // find that the scan is then looking for the first tune value
    // which fails to produce confirmation; that tune value minus 1
    // represents the high end of the confirmed range.
    //

    confirmedTuneRangeLow = confirmedTuneRangeHigh = TUNE_VALUE_INVALID;

    for (tuneValue=MIN_TUNE_VALUE; tuneValue<=MAX_TUNE_VALUE; tuneValue++) {

        //
        // set next AF tune value, allow time for PDAF to resample the
        // phase with the new AF TUNE value
        //
        set_afma(tuneValue, -1);
        msleep(AF_TUNE_CHANGE_SETTLE_TIME_MS);

        //
        // detect how long it takes for PD to sample a successful focus
        // confirmation. based on user-level observations, if there is
        // any perceptible delay between half-pressing the shutter and
        // getting the first focus confirmation then the focus confirmation
        // should be disregarded and the AF TUNE value not included in
        // the tuning range. since our logic is sampling an internal
        // firmware variable to detect focus confirmation, we would
        // need some way to "turn off" the camera's PD sensing so that
        // we can detect a fresh PD sensing transition akin to a half-press
        // of the shutter. if no such mechanism exists then our logic will
        // likely only be useful for AF tune changes that transition
        // from a non-confirmed to confirmed values (ie, when we're looking
        // for the high end of the range). if so, we might consider
        // changing the algorithm so that we start scanning from the opposite
        // end of the AF tune scale to find the high-end of the range
        //
        waitTimeMs = 0;
        do {
            if (is_focus_confirmed())
                break;
            msleep(10);
            waitTimeMs += 10;
        } while (waitTimeMs < MAX_TIME_TO_FIRST_FOCUS_CONFIRM_MS);

        if (waitTimeMs < MAX_TIME_TO_FIRST_FOCUS_CONFIRM_MS) {
            //
            // detected first focus confirmation within the time period
            // allowed. now make sure the focus confirmation stays
            // continuously on for our threshold before we consider
            // the current tune value part of the confirmed range
            //
            waitTimeMs = 0;
            do {
                if (!is_focus_confirmed())
                    break;
                msleep(10);
                waitTimeMs += 10;
            } while (waitTimeMs < MIN_CONTINUOUS_FOCUS_CONFIRM_TIME_MS);

            if (waitTimeMs >= MIN_CONTINUOUS_FOCUS_CONFIRM_TIME_MS) {
                //
                // focus remained confirmed for the duration we require, so
                // current AF tune value was confirmed to be part of the
                // confirmed range
                //
                if (confirmedTuneRangeLow == TUNE_VALUE_INVALID) {
                    // we just found the first end of the range (low end)
                    confirmedTuneRangeLow = tuneValue;
                    continue; // advance to next tune value to start searching high-end of range
                } else
                    //
                    // we've previously found the low end of the tune range and
                    // are trying to find the first non-confirmed tune
                    // value to establish the high-end of the range
                    //
                    continue; // advance to next tune value
            } // else focus confirmation failed to sustain for minimum time allowed
        } // else first focus confirmation didn't occur within max time allowed

        //
        // we reach this point if the current AF tune value is not confirmed
        //
        if (confirmedTuneRangeLow != TUNE_VALUE_INVALID) {
            //
            // we've previously found the low end of the tune range and now
            // found our first tune value which is non-confirmed, meaning
            // the high-end of the confirmed range is the current value
            // minus 1
            confirmedTuneRangeHigh = tuneValue-1;
            break; // done finding range; no more tune values to check
        }
    } // end of AF tune scan loop

    if (confirmedTuneRangeLow != TUNE_VALUE_INVALID && confirmedTuneRangeHigh != TUNE_VALUE_INVALID)
        //
        // DotTune successful. Optimal tune value is midpoint of range.
        // if the midpoint is between two whole values then we round down
        //
        return (confirmedTuneRangeHigh - confirmedTuneRangeLow)/2 + confirmedTuneRangeLow;

    if (confirmedTuneRangeLow == TUNE_VALUE_INVALID) {
        //
        // no AF tune values produced a confirmation, which likely
        // means critical focus was not properly achieved prior
        // to calling this routine
        //

        // show appropriate message to user
        ;
    } else {
        //
        // we found the low end of the range but +20 still produced a focus
        // confirmation, so the high end of the range is beyond +20, meaning
        // we can't find the precise midpoint
        //
       
        // show appropriate message to user
        ;
    }
    return TUNE_VALUE_INVALID; // indicate DotTune failed
}


a1ex

1. Both. Sampling issue is actually something minor IMO.

2. It needs shutter pressed halfway (SW1).

3. The initial guess seems good.

The idea of waiting for continuous confirmation for 5 seconds is interesting, but in practice I don't think it will work (at least with my setup - 5D2 looking at some very small print). If the confirmation is strong, there are multiple focus beeps, and the dot blinks (but it's mostly on).

Also, camera's AF algorithm is not 100% reliable, so finding the range doesn't quite work. If the AF misses some spot in the middle of the range, the end point will be wrong. So, I prefer the current method, because it's much more statistically robust (even if it uses mean, not median).

I also have a problem when sometimes I get focus confirmations over the entire range. Not sure what it causes this, but changing micro AF in Canon menu seems to solve it. Probably the method I'm using for changing AF value isn't quite right.

horshack

Quote from: a1ex on February 22, 2013, 09:21:17 PM
1. Both. Sampling issue is actually something minor IMO.

2. It needs shutter pressed halfway (SW1).

3. The initial guess seems good.

The idea of waiting for continuous confirmation for 5 seconds is interesting, but in practice I don't think it will work (at least with my setup - 5D2 looking at some very small print). If the confirmation is strong, there are multiple focus beeps, and the dot blinks (but it's mostly on).

Also, camera's AF algorithm is not 100% reliable, so finding the range doesn't quite work. If the AF misses some spot in the middle of the range, the end point will be wrong. So, I prefer the current method, because it's much more statistically robust (even if it uses mean, not median).

I also have a problem when sometimes I get focus confirmations over the entire range. Not sure what it causes this, but changing micro AF in Canon menu seems to solve it. Probably the method I'm using for changing AF value isn't quite right.

Thanks for the replies a1ex, much appreciated. Regarding the robustness of either approach, I think it's going to come down to how the behavior of the internal FOCUS_CONFIRMATION flag correlates to the VF confirmation behavior. If the flag matches the VF behavior, I think the negative-exclusion approach of my code snippet above would be necessary to produce a reliable midpoint/AF-tune value, at least based on feedback from the DotTune beta testers on the original FM thread. In particular, the lag to the initial confirmation and the sustaining of the confirmation without any dropouts were found to be critical for successful tuning, and these aspects might not be captured by a weighted, positive-only sampling of the confirmation, unless perhaps there were a very large number of samples over a long period of time. If however you find the flag behaves differently than the VF confirmation then that would certainly require a different approach to the programmatic implementation vs the user-lever method.

As for the ranging and midpoint method, that's been validated on both Nikon and Canon bodies and feedback indicates it's highly accurate with good precision/repeatability, again at least based on the user-level feedback provided by the VF. There shouldn't be nonlinearities or gaps in the confirmed range.

a1ex

The confirmation flag matches the green dot, as far as I could tell.

But even with still camera and high-contrast test pattern, I couldn't get the dot steady for too long. Maybe it was because of artificial light (didn't try in daylight yet).

I'll try to figure it out for 5D3, so you can experiment with the algorithm.

Edit: works on 5D3, you can give it a try.

horshack

Quote from: a1ex on February 22, 2013, 10:54:44 PM
The confirmation flag matches the green dot, as far as I could tell.

But even with still camera and high-contrast test pattern, I couldn't get the dot steady for too long. Maybe it was because of artificial light (didn't try in daylight yet).

I'll try to figure it out for 5D3, so you can experiment with the algorithm.

Edit: works on 5D3, you can give it a try.

Thanks again. I got the build environment set up and I'm able to compile the 5D3 autoexec.bin, albeit with a few compiler warnings which I assume are ok? Based on what I've pieced together from google searches, this is what I do:


  • Unzip contents of the 5D3 Alpha 3 release to root directory of an SD card that's been formatted in-camera
  • Copy 5D3-113-bootflag.fir to the root directory
  • Copy my compiled autoexec.bin to the root directory
  • Run EOScard.exe and select EOS_DEVELOP and BOOTDISK boxes
  • Make sure I'm running 1.1.3 of Canon's 5D3 FW
  • Power on camera and perform perform upgrade using the SD card with ML on it

Is that about it? And I just recopy new autoexec.bin and do fresh firmware updates to test each of my compiles? Anything else I should know?

1%

Figured it out for 6D, prop is different but old prop still there just dead.

a1ex

Yes, the install procedure is correct. You need to run firmware update only once; after that, just copy the new autoexec.bin.

a1ex

Just modified the algorithm, so it detects steady (strong) focus confirmations and scores them more (weak confirmation = 1, strong confirmation = 3).

Here's my typical score graph:



Notice it looks kinda like a Gaussian curve with a bunch of outliers, and possibly some gaps in the middle. Currently, the only outlier filter is weight=score(i)^4, maybe median could work better.

horshack

Thanks again for the help! Got alpha 3 installed and I'm able to test my own builds. My first task was to compare the programmatic check of the FOCUS_CONFIRMATION variable against the VF feedback and I'm excited to report they're essentially identical. The most critical aspect of DotTune is being able to distinguish confirmed vs non-confirmed values, which on Canon bodies involves very tight timing between the half-press and the first confirmation, along with a continuous confirmation without any dropouts (meaning multiple beeps/dot flickers). I have a particular lens + focus distance setup that causes both these scenarios to negative-confirm at one of the AF tune values and FOCUS_CONFIRMATION matched the VF behavior exactly. This gives me a lot of confidence that the programmatic negative-confirmation methodology will match the user-level DotTune success very well.

I have a few more questions...sorry :)

The 5D3 supports 2 tune values per lens, which is used for zoom lenses so you can tune at each end of the zoom range. It doesn't look like the ML tune property logic that was checked-in is aware of this. I was worried about that so for now I've commented out the programmatic AFMA-changing logic until I can be sure that the logic wont corrupt the NVRAM config on my 5D3. How do you usually go about reverse-engineering the property area, so that we can figure out the data structure for the new 2nd value?

What is the purpose of the "fake_simple_button(BGMT_INFO);" in the AFMA logic you wrote? I put it in my test routine and it cycles through a few info screens before getting to my logic. Is that used so that you have an active on-screen canvas to display messages on? (ie, the NotifyBox calls not work properly without the display being made active)

Regarding simulating a half-press of the shutter, I assume SW1(1,100) asserts a simulated press while SW1(0,100) deasserts it? Is the assign_af_button_to_halfshutter() before those necessary to associate that remote simulate to the shutter?

Thanks again,

Horshack

a1ex

1. Didn't know that (my only AF lenses are 50/1.8 and 18-55 kit), but I've noticed two tune values that were changing together: AFMA_PER_LENS_A and AFMA_PER_LENS_B. So I just set both to the same value.

To find the offsets, I just print that buffer, change numbers in Canon menu and see what happens.

I've tried both per-lens and all-lenses adjustments on 5D3 (also turning the camera off in the middle of the process) and it's still alive. I don't think anyone else tried this on 5D3.

2. BGMT_INFO turns the display on.

3. assign_af_button_to_halfshutter disables the back-button AF, if set. Otherwise you won't get focus confirmation.

discocalculi

Looks interesting. I got a few malfocusing lenses that might benefit from this. One had as strong malfocus as around -15/+15 on the Canon fine-tune, and when it got returned from the camera-shop service it pretty much acted the same.

a1ex

I've also tried to expand the range to -40...40 and seems to work, the camera is still alive (5D2).

So, the theoretical range would be -127...127. Could this be useful?

If you try on other camera, try in C mode first, to prevent wrong settings being saved in NVRAM.

horshack

Quote from: a1ex on February 23, 2013, 12:04:08 PM
I've also tried to expand the range to -40...40 and seems to work, the camera is still alive (5D2).

So, the theoretical range would be -127...127. Could this be useful?

If you try on other camera, try in C mode first, to prevent wrong settings being saved in NVRAM.

Absolutely this could be very useful. We'll need to see if the PDAF system itself actually supports these values. If it does this could help a lot of people whose tuning range exceeds +/-20.

horshack

Here is my first DotTune under ML! Early indications are it's producing midpoints very close to the manual procedure. More testing is needed though. Also needs a nice UI if anyone is around who knows ML and is interested  :)



Here's the source:

#ifdef FEATURE_AFMA_TUNING
//
// Dot-Tune constants
//
#define AF_TUNE_CHANGE_SETTLE_TIME_MS        (10)   // time for PDAF to resample phase after changing AF tune (swag)
#define MAX_TIME_TO_FIRST_FOCUS_CONFIRM_MS   (300)  // max time we allow before 1st focus confirmation (swag)
#define MIN_CONTINUOUS_FOCUS_CONFIRM_TIME_MS (5000) // min time that focus confirmation must remain TRUE

int check_dottune_focus(void)
{

    int waitTimeMs;

    //
    // detect how long it takes for PD to sample a successful focus
    // confirmation. based on user-level observations, if there is
    // any perceptible delay between half-pressing the shutter and
    // getting the first focus confirmation then the focus confirmation
    // should be disregarded and the AF TUNE value not included in
    // the tuning range.
    //
    waitTimeMs = 0;
    do {
        if (FOCUS_CONFIRMATION)
            break;
        msleep(10);
        waitTimeMs += 10;
    } while (waitTimeMs < MAX_TIME_TO_FIRST_FOCUS_CONFIRM_MS);

    if (waitTimeMs >= MAX_TIME_TO_FIRST_FOCUS_CONFIRM_MS)
        // no initial focus confirmation within time period allowed
        return 0;

    //
    // detected first focus confirmation within the time period
    // allowed. now make sure the focus confirmation stays
    // continuously on for our threshold before we consider
    // the current tune value part of the confirmed range
    //
    waitTimeMs = 0;
    do {
        if (!FOCUS_CONFIRMATION)
            break;
        msleep(10);
        waitTimeMs += 10;
    } while (waitTimeMs < MIN_CONTINUOUS_FOCUS_CONFIRM_TIME_MS);

    if (waitTimeMs < MIN_CONTINUOUS_FOCUS_CONFIRM_TIME_MS)
        // focus dropped during continuous focus check
        return 0;

    //
    // focus remained confirmed for the duration we require, so
    // current AF tune value was confirmed to be part of the
    // confirmed range
    //
    return 1;
}


void afma_auto_tune()
{

    #define TUNE_VALUE_INVALID              (INT_MIN)
    #define MIN_TUNE_VALUE                  (-20)
    #define MAX_TUNE_VALUE                  (20)
 
    int tuneValue, focusConfirmed;
    int confirmedTuneRangeLow, confirmedTuneRangeHigh;

    int afma0 = get_afma(-1);
   
    msleep(1000);
   
    if (lv) { fake_simple_button(BGMT_LV); msleep(1000); }
   
    for (int i = 0; i < 5; i++)
    {
        if (!DISPLAY_IS_ON || !display_idle())
        {
            fake_simple_button(BGMT_INFO);
            msleep(500);
        }
    }

    if (lv) { NotifyBox(5000, "Turn off LiveView and try again."); beep(); return; }
    if (!DISPLAY_IS_ON || !display_idle()) { NotifyBox(5000, "Press " INFO_BTN_NAME " and try again."); beep(); return; }
    if (!is_manual_focus()) { NotifyBox(5000, "Switch to MF and try again."); beep(); return; }
    if (!lens_info.name[0]) { NotifyBox(5000, "Attach a chipped lens and try again."); beep(); return; }

#ifdef DONT_COMPILE_YET // wait until development is done before delaying on these msgs
    NotifyBox(5000, "You should have perfect focus.");
    msleep(2000);
    NotifyBox(5000, "Leave the camera still...");
    msleep(2000);
    NotifyBoxHide();
    msleep(100);
#endif
   
    assign_af_button_to_halfshutter();
    msleep(100);

    //
    // algorithm: with critical focus already established prior to
    // this routine being called, we scan through the full +/- 20
    // AF tune range to find the range of values which produce
    // an immediate and consistent focus confirmation, then use
    // the midpoint of that confirmed range as the optimal AF tune value.
    //
    // when the scan starts we're looking for the first tune value
    // that produces an immediate and consistent focus confirmation;
    // that represents the low end of the confirmed range. once we
    // find that the scan is then looking for the first tune value
    // which fails to produce confirmation; that tune value minus 1
    // represents the high end of the confirmed range.
    //
    confirmedTuneRangeLow = confirmedTuneRangeHigh = TUNE_VALUE_INVALID;

    for (tuneValue=MIN_TUNE_VALUE; tuneValue<=MAX_TUNE_VALUE; tuneValue++) {
       
        NotifyBox(1000, "Checking AF Tune %d", tuneValue);

        //
        // set next AF tune value to test, allow time for PDAF
        // to resample the phase with the new AF TUNE value
        //
        set_afma(tuneValue,-1);
        msleep(AF_TUNE_CHANGE_SETTLE_TIME_MS);

        //
        // check the focus at this AF tune value
        //
        SW1(1,100);
        focusConfirmed = check_dottune_focus();
        SW1(0,100);

        //
        // process focus result
        //
        if (focusConfirmed) { // focus confirmed for current tune value
            if (confirmedTuneRangeLow == TUNE_VALUE_INVALID) {
                // we just found the first end of the range (low end)
                confirmedTuneRangeLow = tuneValue;
                continue; // advance to next tune value to start searching high-end of range
            } else
                //
                // we've previously found the low end of the tune range and
                // are trying to find the first non-confirmed tune
                // value to establish the high-end of the range, so keep scanning
                //
                continue; // advance to next tune value
        } else  { // focus not confirmed for current tune value
            if (confirmedTuneRangeLow != TUNE_VALUE_INVALID) {
                //
                // we've previously found the low end of the tune range and now
                // found our first tune value which is non-confirmed, meaning
                // the high-end of the confirmed range is the current value
                // minus 1
                //
                confirmedTuneRangeHigh = tuneValue-1;
                break; // done finding range; no more tune values to check
            }
        }
    }
   
    restore_af_button_assignment();

    if (confirmedTuneRangeLow != TUNE_VALUE_INVALID && confirmedTuneRangeHigh != TUNE_VALUE_INVALID) {
        //
        // DotTune successful. Optimal tune value is midpoint of range.
        // if the midpoint is between two whole values then we round down
        //
        int midpoint = (confirmedTuneRangeHigh - confirmedTuneRangeLow)/2 + confirmedTuneRangeLow;
        set_afma(midpoint,-1);
        NotifyBox(5000, "Success: Mid=%d (range=%d..%d)",
                midpoint, confirmedTuneRangeLow, confirmedTuneRangeHigh);
        return;
    }

    //
    // DotTune failed
    //
    set_afma(afma0,-1); // restore orig AF tune value
    if (confirmedTuneRangeLow == TUNE_VALUE_INVALID)
        //
        // no AF tune values produced a confirmation, which likely
        // means critical focus was not properly achieved prior
        // to calling this routine
        //
        NotifyBox(5000, "Failed: Image is OOF!");
    else
        //
        // we found the low end of the range but +20 still produced a focus
        // confirmation, so the high end of the range is beyond +20, meaning
        // we can't find the precise midpoint
        //
        NotifyBox(5000, "Failed: +20 exceeded (low=%d)",
                confirmedTuneRangeLow);
}


Horshack

a1ex

Very nice.

I've just added the extended AFMA ranges and they seem to work both on 5D2 and 5D3. They are interpreted properly in PDAF, you can try by defocusing a bit before running the calibration.



Now I'd like to compare both algorithms and see if there are any differences.

horshack

Quote from: a1ex on February 23, 2013, 01:43:44 PM
Very nice.

I've just added the extended AFMA ranges and they seem to work both on 5D2 and 5D3. They are interpreted properly in PDAF, you can try by defocusing a bit before running the calibration.



Now I'd like to compare both algorithms and see if there are any differences.

The extended range support you added is going to be a godsend, not just for when the final AF tune value is beyond +/-20 but also when the DotTune range is beyond +/- 20 but where the midpoint still falls within +/- 20.

How should we go about comparing the algorithms? I have several lenses I could check yours on, but I'm thinking maybe the sample size would be too small. Should we consider leaving both algorithms in and make it user selectable?

Greg

You can enter different values ​​for different AF points?
Example:
Left point: +3
Right point: +5

Francis

I'm will test out the difference algorithms on my 5d2. I'm sure with a few more people from these forums we can get a decent sample size with a number of different lenses.