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.

trsaunders

I'm not sure if the values are correct, it is giving me quite a large adjustment value (-12). Should I have just one focus point selected?
50D, 5D3

Francis

Yes, just 1 focus point.

garry23

All

Once I manage to get the DotTune function up and running in my 50D I will cross check with the other AFA process I use, ie FocusTune.

I have found FocusTune to work well and it provides graphical plots that help provide confidence that you have indeed hit the sweet spot, ie it will be good to see DotTune and FocusTune align!

Cheers

Garry

horshack

Quote from: Marsu42 on February 24, 2013, 11:55:02 AM
Exactly - Canon removed it from the 50d->60d to make the 7d look better (thanks, Canon!). But probably all they did was commenting it out in the ui, so it would be a godsend it you'd figure out if the 60d internally still supports it...

I'm thinking the same. Probably the easiest way to find out for sure is to enable DotTune for the 60D build and see if it finds any tune value between +/- 20 that doesn't produce focus confirmation, as this would imply the 60D's PDAF is using those values. This test assumes ML is using the correct NVRAM property location for the 60D's AF tune values.

Marsu42

Quote from: horshack on February 24, 2013, 05:55:49 PM
This test assumes ML is using the correct NVRAM property location for the 60D's AF tune values.

Indeed - but how to find them, if you cannot do anything afma'ish in the ui? I hope some dev with a lot of insight into the Canon property structures can either give it a try so we can put out hopes to rest :-\

1%

Its a little bit of a dead end on 600D as nothing wants to enable the property. If 60D property is also 5 then we have to look elsewhere. I did see the graph and it did come up with a value a few times but no way to keep it enabled.

horshack

Alex,

I've been tied up this weekend but I'm getting back to this for more testing. Q about the current algo - I noticed your two focus loops continue to execute even after detecting FOCUS_CONFIRMATION. Is this done intentionally for downstream timing, because I can't see any other side effect otherwise. If I insert a break after FOCUS_CONFIRMATION I get the same tune results and shave about 30 seconds off the DotTune time, dropping from 1:47 to 1:18 for a range that has about 20 tune units.

Here's the modified source (change in red):

// check for focus confirmation
            int fc = 0;
            for (int j = 0; j < 20; j++)
            {
                msleep(10);
                if (FOCUS_CONFIRMATION) {
                    fc = 1;
                    break;
                }
            }
           
            // weak or strong confirmation? use a higher score if strong
            if (fc)
            {
                msleep(500);
                for (int j = 0; j < 20; j++)
                {
                    msleep(10);
                    if (FOCUS_CONFIRMATION) {
                        fc = 3;
                        break;
                    }
                }
            }

Thanks,

Horshack

eolia

Where can we get the nighty to help debug ?

a1ex

Click on Download.

@horshack: correct, the focus loops don't have to keep executing, as the msleep(100) before the first loop is enough.

You may also want to review this: https://bitbucket.org/hudson/magic-lantern/commits/6334a26c16a9

horshack

Alex,

That change looks good. I haven't tested the expanded ranges yet; if for whatever reason those don't work out we might want to replace the user suggestion of trying a wider range with a warning message that the new tune value may not be reliable since -20 or +20 were part of the range.

Today I spent about an hour on the core timing of the focus confirmation detection, comparing it to my own visual AF confirmation checks. Rather than just verifying the final calculated value like I was before, today I was comparing the behavior of individual tune values at the periphery of the tuning range. Your algo vs my visual check matches well; your idea to do 4 sweeps is perfect because I do see a blip on one or two passes so the 4 passes is just right for normalizing them out.

The only worthwhile improvement I found was to change to 500ms dead delay into a continuous FOCUS_CONFIRMATION check; right now the code is waiting 500ms and then sampling in a separate loop, which misses some multiple-beep/confirmation cases I see at the outliers on my 50mm f/1.4 (ie, tune values that should be discarded but are included). So rather than sampling for one positive confirmation after 500ms it catches more blips if we sample continuously.

Here's the proposed change. Since this change involves another sampling loop I consolidated that into a separate nested function. Let me know what you think...

    SW1(1,100);

    int wait_for_focus_confirmation_val(int maxTimeToWaitMs, int valToWaitFor)
    {
        int timeWaitedMs = 0;
        for ( ;; )
        {
            if (FOCUS_CONFIRMATION == valToWaitFor)
                return 1; // detected value
            if (timeWaitedMs >= maxTimeToWaitMs)
                return 0; // timed-out before detecting value
            msleep(10);
            timeWaitedMs += 10;
        }
    }

    for (int k = 0; k < 2; k++)
    {
        for (int c = 0; c <= 80; c++) // -20 ... 20 and back to -20
        {
            int i = (c <= 40) ? c-20 : 60-c;
            set_afma(i * range_expand_factor, AFMA_MODE_AUTODETECT);
            msleep(100);
           
            int fc;
            // initial focus must occur within 200ms
            fc = wait_for_focus_confirmation_val(200, 1);
           
            if (fc)
            {
                // weak or strong confirmation? use a higher score if strong
                // focus must sustain for 500ms to be considered strong
                if (!wait_for_focus_confirmation_val(500, 0))
                    // focus sustained
                    fc = 3;
            }
           
            score[i+20] += fc;
            afma_print_status(score, range_expand_factor);
           
            if (!HALFSHUTTER_PRESSED)
            {
                beep();
                set_afma(afma0, AFMA_MODE_AUTODETECT);
                NotifyBox(2000, "Canceled by user.");
                return;
            }
        }
    }
    SW1(0,100);

Thanks,

Horshack

horshack

Alex,

I added logic for the 5DM3's unique wide/tele AFMA support. The source is below. When DotTuning a zoom and specifying a wide vs tele value (instead of "both"), the user needs to make sure he sets his lens focal length to match where he'll be storing his wide/tele tune value before starting the DotTune, because otherwise the 5DM3's firmware will interpolate AF tune values between the wide and tele settings and this is not desirable when tunning. For example, when focusing (or evaluating focus via the VF confirmation), if AFMA is -5 for wide and -10 for tele on a 70-200mm lens, @ 70mm the 5DM3 firmware will use -5, @ 200mm it will use -10, and for any focal length in between it will use a scaled value between -5 and -10, per Canon's 5DM3 manual and my observations as well.

Here's the source. Again I'm new to ML so this might require some modification as you see fit. Thanks!

src/dryos.h:
/** AF microadjustment **/
int get_afma(int mode, int focalVal);
void set_afma(int value, int mode, int focalVal);
#define AFMA_MODE_AUTODETECT -1
#define AFMA_MODE_DISABLED 0
#define AFMA_MODE_ALL_LENSES 1
#define AFMA_MODE_PER_LENS 2
#define AFMA_FOCAL_VAL_BOTH 0
#define AFMA_FOCAL_VAL_WIDE 1
#define AFMA_FOCAL_VAL_TELE 2


platform/5D3 cfn.c:
// 5D3 only; other cameras have different offsets, buffer size etc
#define PROP_AFMA_CFN 0x80040027
static int8_t afma_buf[0x10];
#define AFMA_MODE          afma_buf[0x0]
#define AFMA_PER_LENS_WIDE afma_buf[0x2]
#define AFMA_PER_LENS_TELE afma_buf[0x3]
#define AFMA_ALL_LENSES    afma_buf[0x5]

int get_afma(int mode, int focalVal)
{
    if (mode == AFMA_MODE_AUTODETECT) mode = AFMA_MODE;
   
    if (mode == AFMA_MODE_PER_LENS)
        // for AFMA_FOCAL_VAL_BOTH, return AFMA_PER_LENS_WIDE
        return (focalVal <= AFMA_FOCAL_VAL_WIDE ? AFMA_PER_LENS_WIDE : AFMA_PER_LENS_TELE);

    else if (mode == AFMA_MODE_ALL_LENSES)
        return AFMA_ALL_LENSES;

    return 0;
}

void set_afma(int value, int mode, int focalVal)
{
    if (ml_shutdown_requested) return;

    value = COERCE(value, -AFMA_MAX, AFMA_MAX);

    if (mode == AFMA_MODE_AUTODETECT) mode = AFMA_MODE;
    if (mode == AFMA_MODE_DISABLED) mode = AFMA_MODE_ALL_LENSES;
   
    if (mode == AFMA_MODE_PER_LENS) {
        if (focalVal == AFMA_FOCAL_VAL_BOTH)
            AFMA_PER_LENS_WIDE = AFMA_PER_LENS_TELE = value;
        else if (focalVal == AFMA_FOCAL_VAL_WIDE)
            AFMA_PER_LENS_WIDE =  value;
        else if (focalVal == AFMA_FOCAL_VAL_TELE)
            AFMA_PER_LENS_TELE = value;
        else return; // bad arguments
    }
   
    else if (mode == AFMA_MODE_ALL_LENSES)
        AFMA_ALL_LENSES = value;
   
    else return; // bad arguments
   
    AFMA_MODE = mode;
    prop_request_change(PROP_AFMA_CFN, afma_buf, sizeof(afma_buf));
}


platform/5D2 cfn.c:
int get_afma(int mode, int focalVal /* not supported on 5D2 */)
{
    if (mode == AFMA_MODE_AUTODETECT) mode = AFMA_MODE;
   
    if (mode == AFMA_MODE_PER_LENS)
        return AFMA_PER_LENS;

    else if (mode == AFMA_MODE_ALL_LENSES)
        return AFMA_ALL_LENSES;

    return 0;
}

void set_afma(int value, int mode, int focalVal /* not supported on 5D2 */)
{
    if (ml_shutdown_requested) return;

    value = COERCE(value, -AFMA_MAX, AFMA_MAX);

    if (mode == AFMA_MODE_AUTODETECT) mode = AFMA_MODE;
    if (mode == AFMA_MODE_DISABLED) mode = AFMA_MODE_ALL_LENSES;

    if (mode == AFMA_MODE_PER_LENS)
        AFMA_PER_LENS = value;
   
    else if (mode == AFMA_MODE_ALL_LENSES)
        AFMA_ALL_LENSES = value;
   
    else return; // bad arguments

    AFMA_MODE = mode;
    prop_request_change(PROP_AFMA_CFN, afma_buf, sizeof(afma_buf));
}


src/focus.c:
#ifdef FEATURE_AFMA_TUNING

CONFIG_INT( "focal_afma_value_select", focal_afma_value_select, AFMA_FOCAL_VAL_BOTH);

static void afma_print_status(int8_t* score, int range_expand_factor)
{

Changed all get_afma() and set_afma() calls in focus.c to pass "focal_afma_value_select" as final argument, which includes afma_print_status(), afma_auto_tune(), MENU_UPDATE_FUNC(afma_display), and MENU_SELECT_FUNC(afma_toggle)

            {
                .name = "AF microadjust",
                .update = afma_display,
                .select = afma_toggle,
                #ifdef CONFIG_AFMA_EXTENDED
                .help  = "Adjust AFMA value manually. Range: -100...+100.",
                #else
                .help  = "Adjust AFMA value manually. Range: -20...+20.",
                #endif
                .edit_mode = EM_MANY_VALUES,
            },
#if defined(CONFIG_5D3)
            {
                .name = "Wide/Tele Select",
                .priv = &focal_afma_value_select,
                .max = 2,
                .choices = (const char *[]) {"Both/Prime", "Wide(Zoom)", "Tele(Zoom)"},
                .help = "Body supports two AFMA values for zoom lenses.",
            },
#endif
            MENU_EOL
        },
    },
};




pulsar124

Thanks for the efforts - fantastic project! I just wish one day you will figure out how to make MFA values FL and/or distance dependent.

I gave a try to the nightly built on my 50D, and happy to report that it seems to be working fine. I will do more thorough testing with good light and target, comparing ML/dot-tune results to FoCal results, on my fast lenses (135mm f2.0, 17-50mm f2.8, 70-200mm f4).

1%

Great! 6D has wide/tele too. Saves me from doing 2 tests like was suggested earlier.

Jansten

Can this be implented in the apha 3 for the 7d?
I know 7d have only one micropoint for adjustment, but you guys have sorted out that already, I understood
It would be great not to use lens- align to calibrate the lens i own
And Just use the Dot-tune feature

Keep up the good work :)

g3gg0

it will be in alpha 3
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

Just did a slightly bigger change: besides adding support for wide/tele adjustments, I've moved all AFMA code to afma.c and kept only the constants in platform directory (afma.h).

So... it needs some testing to make sure I didn't break anything.

1%

Menu parts work so far. Going to have to try the adjustments. I think we still have to manually register the lens if we want to use per lens? Only other improvement I can think of.

Francis

I have a 100mm macro lens that I use both for macro shots and for portraits. Running DotTune at both a macro and a portrait distance gives different results (-5 at portrait, +4 at macro). Sound I use the average? 0 and -1 lies in the acceptable range for both. Does that sound reasonable or am I missing something? The author suggests 50 x focal length. I almost never use this lens at 5m so it doesn't seem appropriate to set the MA at that distance.

rktaylor

I'm new at this but if I understand correctly this will auto calibrate my lenses with the proper AFMA and adjust appropriately in my C.FnII: Autofocus settings for each lens ... correct?

Here are the steps I followed with all four (see below for my lenses) I own.

1.  Good Lighting
2.  Set to manual focus
3.  Focus on high contrast subject ... in my case I used a focus graph found on internet
4.  Go to DotTurne and scan with default (-20...+20)
5.  Ran through testing

the results was Zero with all of my lenses ... does that seem right?
If I did get an adjustment would it auto recognize the lenses attached and use the appropriate adjustment.

As you can see below my camera is a Canon 6D

Thanks
6D | Tamron 24-70 f/2.8 | EF 50 f/1.4 | EF 70-300 f/4-5.6 | Canon EF 100mm f/2.8 L

horshack

Quote from: a1ex on March 03, 2013, 01:19:14 PM
Just did a slightly bigger change: besides adding support for wide/tele adjustments, I've moved all AFMA code to afma.c and kept only the constants in platform directory (afma.h).

So... it needs some testing to make sure I didn't break anything.

Thanks Alex. Works fine on my 5DM3. The only new issue I found is if the user cancels or DotTune ends in error, the final call to set_afma(afma0, afma_mode) will fail to properly restore the original tune value when afma_mode is AFMA_MODE_PER_LENS, since get_afma(AFMA_MODE_PER_LENS) returns the midpoint of the wide/tele settings for #CONFIG_AFMA_WIDE_TELE builds:

return (AFMA_PER_LENS_WIDE + AFMA_PER_LENS_TELE) / 2;

The logic in afma_auto_tune() will need to save off and restore both wide/tele values for the user cancelled/DotTune failed case.

I'm also thinking we might want to consider removing the "both" mode for #CONFIG_AFMA_WIDE_TELE builds and instead force the user to always set wide or tele. This is based on my reading on the 5DM3 manual - when only a single value is configured (wide or tele), the camera will still scale that tune value for other focal lengths on the zoom, and so having the wide+tele set to the same tune value might not be ideal for the majority of users, even if it would be useful for a small percentage of them.

horshack

Quote from: Francis on March 03, 2013, 06:15:42 PM
I have a 100mm macro lens that I use both for macro shots and for portraits. Running DotTune at both a macro and a portrait distance gives different results (-5 at portrait, +4 at macro). Sound I use the average? 0 and -1 lies in the acceptable range for both. Does that sound reasonable or am I missing something? The author suggests 50 x focal length. I almost never use this lens at 5m so it doesn't seem appropriate to set the MA at that distance.

It's not unsual for lenses to exhibit focus-distance variance in tune values. You can either choose the value for a single distance if that's what you shoot at most often, or use the midpoint of the distance values if that produces acceptable results for you.

1%

Should not be 0 on most lenses. Canon menu -> lcd on/off remains on. What happens with the squares? I just ran on tokina 11-16 again in less than perfect focus and got +11.

So what happens with all lenses? Doesn't scale?

rktaylor

Quote 1%:

Should not be 0 on most lenses. Canon menu -> lcd on/off remains on. What happens with the squares? I just ran on tokina 11-16 again in less than perfect focus and got +11.

So what happens with all lenses? Doesn't scale?


Sorry very busy time of the year for me and have not had time to figure out the quote option ... but ...

If you are referring to the 'Live view Shoot' option it is enabled.

The squares (for all four lenses) are successful (large boxes) all the way across the screen both ways ... I'm sure I'm not doing something right.  Under the AFMA mode I've tested only for 'This Lens' and have not run the test for 'All Lenses'.  I'm not sure what you mean about 'Doesn't scale'.

When I have a spare time I'll continue testing.  Thanks for the response.
6D | Tamron 24-70 f/2.8 | EF 50 f/1.4 | EF 70-300 f/4-5.6 | Canon EF 100mm f/2.8 L

a1ex

For prime lenses, the 5D3 uses the wide adjustment (and ignores the tele one).

1%

But is "all lenses" scaled across focal length too? Lots of little quirks it seems.