Focus backend updates - precise focus position and other tweaks

#748 Merged at 17a8ea8
Repository
Branch
focus
Repository
Branch
lua_fix
Author
  1. Alex
Reviewers
Description

See http://www.magiclantern.fm/forum/index.php?topic=4997

Exposed the focus motor position counter (relative) to lens_info.focus_pos (or, in Lua, lens.focus_pos). This counter has some nice properties: it appears to be the motor encoder output, as it doesn't lose track of its position, as long as the focus ring is moved by the internal motor.

TODO: combine motor position (high-res, relative, unknown origin, may lose position with MF) with focus distance reports (low-res, absolute, direction-dependent, probably with good repeatability) to get a precise estimation of the focus distance.

Also fixed a bug where the lens may get stuck at some endpoint, especially at low speed, even if you tell the lens to move away from that endpoint. This might also help with issue #2452 (not tested).

EOS M: refactored some code - are the focus ring triggers (for magic zoom and 5x/10x zoom) still working?

Note: on EOS M and 6D, the location of this counter is unknown, so I need some help with reverse engineering (just print the contents of PROP_LV_LENS and find out which offset contains the focus motor position). The current state would break the 6D and EOS M builds.

Comments (23)

  1. Daniel Fort

    Compiling EOSM gets bumpy around here:

    [ CC       ]   bitrate.o
    In file included from ../../src/bitrate.c:5:0:
    ../../src/bitrate.c: In function 'time_indicator_show':
    ../../src/bitrate.c:374:81: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
             int fnts = FONT(FONT_SMALL, COLOR_WHITE, mvr_config.actual_qscale_maybe == -16 ? COLOR_RED : COLOR_BLACK);
                                                                                     ^
    ../../src/bmp.h:174:13: note: in definition of macro 'FONT'
             | ((bg) & 0xFF) << 8 \
                 ^
    ../../src/bitrate.c:379:23: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
                 mvr_config.actual_qscale_maybe < 0 ? "-" : "+",
                           ^
    [ CC       ]   lcdsensor.o
    [ CC       ]   tweaks.o
    [ CC       ]   tweaks-eyefi.o
    [ CC       ]   lens.o
    ../../src/lens.c: In function '_prop_handler_PROP_LV_LENS':
    ../../src/lens.c:1536:57: error: 'const struct prop_lv_lens' has no member named 'focus_pos'
         lens_info.focus_pos     = (int16_t) bswap16( lv_lens->focus_pos );
                                                             ^
    make: *** [lens.o] Error 1
    
    1. Alex author

      Yes, that's what you have to find out.

      To answer my other question for EOS M, without finding focus_pos, just comment out that line.

        1. Alex author

          Right, but it's not a simple integer, it's a data structure. You can just print it as an array of uint16_t, but the values are big-endian, so you may have to reverse them.

          I can check the 6D part on 5D3 1.2.3, I'm just too lazy to upgrade back and forth :P

          off_0x08 means the structure field at offset 0x08 (so, if lv_lens is 0x1234, lv_lens->off_0x08 is (uint32_t)0x123c). It's just a naming scheme for unknown structure fields.

          Regarding PROP_LV_FOCUS_DATA, I've looked at a 700D and couldn't find it either.

      1. Daniel Fort

        Commented out src/lens.c line 1536, compiled and ran Script API Tests.

        lens = table:
          name = "EF-M22mm f/2 STM"
          focal_length = 22
          focus_distance = 320
          hyperfocal = 6390
          dof_near = 306
          dof_far = 335
          af = true
          af_mode = 0
          focus = function: p
        

        BTW on the EOSM the test hangs here:

        Testing module 'lv'...
        LiveView is running; stopping...
        

        As far as printing PROP_LV_LENS, sorry I'm at a lost on how to do that.

        1. Alex author

          Ah, right, the EOS M can't turn off LiveView. Does the camera hang completely so you have to take the battery out, or does the test fail with some assert?

          You can comment out test_lv to skip it.

          For printing the values, assuming the counter is still 16-bit, you could do something like this:

          uint16_t* x = (uint16_t*) buf;
          bmp_printf(FONT_MED, 50, 50, "%x %x %x ...", bswap16(x[0]), bswap16(x[1]), bswap16(x[2]), ...);
          
          1. Daniel Fort

            On the EOSM it just kept re-running the part where it tries to turn off LV. No assert, crash or battery pull needed. After removing all traces of test_lv() the tests seemed to run fine.

            I'm still lost on printing the values. Not sure where to insert that code. (Be nice!)

            The test saved some interesting lens information:

            Testing lens focus functionality...
            Focus distance: 140
            Focusing backward...
            Focus distance: 190
            Focus motor position: 0
            Focusing forward with step size 3, wait=true...
            .....
            Focus distance: 655350
            Focus motor position: 0
            Focusing backward with step size 3, wait=true...
            
            Focus distance: 655350
            Focus motor position: 0
            Focus range: 5 steps forward, 0 steps backward. 
            Motor steps: 0 forward, 0 backward, 0 lost. 
            Focusing forward with step size 3, wait=false...
            ...................
            Focus distance: 150
            Focus motor position: 0
            Focusing backward with step size 3, wait=false...
            ...
            Focus distance: 655350
            Focus motor position: 0
            Focus range: 19 steps forward, 3 steps backward. 
            Motor steps: 0 forward, 0 backward, 0 lost. 
            Focusing forward with step size 2, wait=true...
            ................................................................
            Focus distance: 140
            Focus motor position: 0
            Focusing backward with step size 2, wait=true...
            ...
            Focus distance: 1470
            Focus motor position: 0
            Focus range: 64 steps forward, 3 steps backward. 
            Motor steps: 0 forward, 0 backward, 0 lost. 
            Focusing forward with step size 2, wait=false...
            ....................................................................................................................................................................................................................................................................................................................
            Focus distance: 350
            Focus motor position: 0
            Focusing backward with step size 2, wait=false...
            
            Focus distance: 350
            Focus motor position: 0
            Focus range: 308 steps forward, 0 steps backward. 
            Motor steps: 0 forward, 0 backward, 0 lost. 
            Focusing forward with step size 1, wait=true...
            
            Focus distance: 350
            Focus motor position: 0
            Focusing backward with step size 1, wait=true...
            
            Focus distance: 350
            Focus motor position: 0
            Focus range: 0 steps forward, 0 steps backward. 
            Motor steps: 0 forward, 0 backward, 0 lost. 
            Focusing forward with step size 1, wait=false...
            
            Focus distance: 350
            Focus motor position: 0
            Focusing backward with step size 1, wait=false...
            
            Focus distance: 350
            Focus motor position: 0
            Focus range: 0 steps forward, 0 steps backward. 
            Motor steps: 0 forward, 0 backward, 0 lost. 
            
            Focus test completed.
            
            1. Alex author

              Interesting, so the focus test was actually able to move the lens on EOS M? That's good news, although the movement is not consistent (the lens should move back and forth a couple of times).

              Do you have any sort of continuous autofocus enabled? Does it help if you disable it?

              The place to print the above values is the function where you've got the error in your first post. It's the only function that mentions PROP_LV_LENS. For background info, see http://magiclantern.wikia.com/wiki/Properties

              1. Daniel Fort

                I did have the lens on continuous autofocus, disabling it and re-running the test shows that the focus does not move.

                Following your instruction for displaying PROP_LV_LENS this information printed on the screen: 3a9d 4000 3fc6 a000 3c9b a000 bb54 2000

                I'm not sure if eight is enough, should I keep going?

                  1. Daniel Fort

                    That gave me an idea. I put the camera back into continuous autofocus and captured screenshots with the camera focused on two different distances. Does this help?

                    VRAM0.jpg

                    VRAM1.jpg

                    1. Alex author

                      Doesn't look like, but that's the way to find it. Let's try some more numbers. To find out the array size, print len/2.

                      If this is a focus-by-wire lens, that counter would change when you turn the focus ring manually as well. It's similar to focus distance, but much more steps, and is proportional to how much you turn the focus ring (the focus distance is highly nonlinear). Also, it is 0 at power on.

                      So, it's not obvious from only 2 screenshots - you need to check the other hints as well.

                      1. Daniel Fort

                        I don't follow you on how to find the array size. Did some poking around and came up with this:

                        bmp_printf(FONT_MED, 50, 50, "%d", sizeof(bswap16(x)));
                        

                        Which printed out 2. Hope that's of some use.

                        Note that manually focusing the lens will change the counter. I tried out some other lenses and it turns out that the first few digits never change but are different between the EF-M lenses that I have:

                        3a9d 4000 3fc-   22mm
                        bbcc e000 bf--   11-22mm
                        3ba3 c000 3fdf   18-55mm
                        

                        At least from my observations those are the digits that don't change and yes they are different on each lens.

                        1. Alex author

                          In property handlers, you have a variable named len (you won't see it in the declaration, but if you look up the PROP_HANDLER macro, it's there). So, just print len.

                          Since each element in the array is a 16-bit number (two bytes), divide len by 2 to find out the array size.

                          The first 8 bytes are two float32 values. I'm not sure about their exact meaning, but it may be worth checking them as well.

                          1. Daniel Fort

                            print(len); doesn't work but this did:

                            bmp_printf(FONT_MED, 50, 50, "%x %x", len, len/2);
                            

                            This is what it printed: 3d 1e Hope that's of some use.

                            1. Alex author

                              Yes, that means the structure has 0x3D bytes, and if you interpret it as an array of uint16_t, you can use 0x1E items.

                              One of those should be the counter we are looking for.

                              1. Daniel Fort

                                I did this same test with the 700D and it reported:

                                39 1c

                                I assume this camera has already been verified to work with the new code and only searching for the values for the 6D and EOSM. In any case I thought I'd report this result as a sort of sanity check that my tests are providing the right data. I did do another test that might prove interesting but is more complicated to explain so I am shooting a video to show exactly what is going on.

                                1. Alex author

                                  I didn't verify it, but I expect it to work. You could try running api_test.lua on it, if you didn't already.

  2. Daniel Fort

    It seemed that we were getting close to something back on Aug. 26 so I expanded on that test. Here's how I modified src/lens.c:

    PROP_HANDLER( PROP_LV_LENS )
    {
        const struct prop_lv_lens * const lv_lens = (void*) buf;
        lens_info.focal_len     = bswap16( lv_lens->focal_len );
        lens_info.focus_dist    = bswap16( lv_lens->focus_dist );
    //    lens_info.focus_pos     = (int16_t) bswap16( lv_lens->focus_pos );
    
    uint16_t* x = (uint16_t*) buf;
    bmp_printf(FONT_MED, 50, 50, "%x %x %x %x %x %x %x %x %x %x", bswap16(x[0]), bswap16(x[1]), bswap16(x[2]), bswap16(x[3]), bswap16(x[4]),bswap16(x[5]), bswap16(x[6]), bswap16(x[7]), bswap16(x[8]), bswap16(x[9]));
    bmp_printf(FONT_MED, 50, 100, "%x %x %x %x %x %x %x %x %x %x", bswap16(x[10]), bswap16(x[11]), bswap16(x[12]), bswap16(x[13]), bswap16(x[14]),bswap16(x[15]), bswap16(x[16]), bswap16(x[17]), bswap16(x[18]), bswap16(x[19]));
    bmp_printf(FONT_MED, 50, 150, "%x %x %x %x %x %x %x %x %x %x", bswap16(x[20]), bswap16(x[21]), bswap16(x[22]), bswap16(x[23]), bswap16(x[24]),bswap16(x[25]), bswap16(x[26]), bswap16(x[27]), bswap16(x[28]), bswap16(x[29]));
    bmp_printf(FONT_MED, 50, 200, "%x %x %x %x %x %x %x %x %x %x", bswap16(x[30]), bswap16(x[31]), bswap16(x[32]), bswap16(x[33]), bswap16(x[34]),bswap16(x[35]), bswap16(x[36]), bswap16(x[37]), bswap16(x[38]), bswap16(x[39]));
    
        if (lens_info.focal_len > 1000) // bogus values
            lens_info.focal_len = 0;
    

    Below is a link to a video showing what is getting displayed on the LCD. Note that in a prior test I noticed that moving the focus ring had no effect but when I made the video it did have an effect. This was probably because on my previous test the focus might have been at the close or far limit. It is difficult to tell with EF-M lenses where you're at.

    https://youtu.be/4vMHfDx2VAY

  3. Daniel Fort

    I guess this hasn't really helped much but just to make sure, we're looking for the values for focus_pos on the 6D and EOSM, right?

    A bit off topic but it seems that the EOSM controls the EF-M lenses differently than EF lenses via the adapter. In src/lens.h the prop_lv_lens structure has both a focus_dist and a focus_dist2. The focus_dist2 has some addresses but focus_dist does not. Could it be that focus_dist controls EF-M lenses and focus_dist2 controls EF lenses via the adapter? The reason I'm bringing this up is because running api_test.lua with an EF lens attached runs through the lens test rather quickly and it is obvious that the focus is moving while on EF-M lenses it takes a very long time to get through the lens test and there seems to be no activity with the lens focus. Shouldn't we also be looking for the addresses for focus_dist on the EOSM?

    1. Alex author

      Interesting, so EF lenses are given focus commands just like before (some sort of compatibility mode) and EF-M lenses require a new set of commands?

      Side note: that means, if you somehow manage to adapt an EF-M lens to an EF mount (even just by connecting the pins), it won't autofocus?

      1. Daniel Fort
        1. That appears to be true.

        2. In theory. The EF-M has 9 contact pins while EF/EF-S has 8 contact pins (at least on the 700D body it does) so something must be different between the way the camera communicates with the lens.