CMOS/ADTG/Digic register investigation on ISO

Started by a1ex, January 10, 2014, 12:11:01 PM

Previous topic - Next topic

0 Members and 3 Guests are viewing this topic.

IDA_ML

Quote from: a1ex on November 05, 2018, 11:01:11 AM
Reducing to 12-bit levels results in better lossless compression, but the image quality suffers a little (possibly just a negligible amount). Overall, it might be a worthy tradeoff.

Absolutely, A1ex!  This is a very worthy tradeoff.  In my own experience, going from 14 to 12 bit lossless results in a negligible quality degradation but if you could achieve better lossless compression at 12 bits, resulting in longer recording times of contrasty scenes, that would be very welcome.  I am sick and tired of early stops when I direct the camera towards a brighter and more contrasty scene during recording. 

Levas

ADTG2[21] has interesting effects, but definately not gain (I can get horizontal type of dual exposure)
ADTG2[22, 23, 24] don't give any visible effects on 6d  ???

That leaves me with the current known gains/preamps.
Made a preset which I can load in crop_rec module.
According to raw histogram I get 6 extra stops by maxing out analog gain and preamps.
So with highest 'native' iso setting of iso 6400 on 6d, I can get iso 6400 + 6 stops with the preset,
giving an iso setting of 409600.
Only problem for now...is getting a usable picture out of this noisy mess  :P

Danne

Been sweating the registers a few times trying to get some decent results/understaning about what to do here.

Firstly:
QuoteWhen comparing noise at different flavors of ISO 100 (or any other ISO), make sure you capture the same amount of light (i.e. same shutter speed, aperture and test scene). This is important, otherwise the difference in noise will be given by the different amounts of captured light (i.e. the test results will be... well... bogus).
All isos compared were at same settings. i.e iso 100 to iso 100 with lowered analog gains compensated with pushed CMOS[0] value to match brightness by eye in liveview. Also note that if I don´t push CMOS[0] the ouput will still look shitty but only now it´s dark and shitty. Difference could occur if comparing let´s say iso 100 to iso 400 but that is not what we are looking at right now.

Two examples at exact same settings below:
Iso 400(untouched register)


Iso 400(reduced analog gain compensated CMOS[0] to match brightness iso 400)


My crude code:
https://bitbucket.org/Dannephoto/magic-lantern/raw/49f23e49f96129f0777d10e65fdf82942ef48522/modules/crop_rec/crop_rec.c
     if (is_5D3)
         {
    case CROP_PRESET_mv1080p_iso100:
    case CROP_PRESET_mv1080p_iso200:
    case CROP_PRESET_mv1080p_iso400:
    case CROP_PRESET_mv1080p_iso800:
    case CROP_PRESET_mv1080p_iso1600:
    case CROP_PRESET_mv1080p_iso3200:
adtg_new[13] = (struct adtg_new) {6, 0x8882, 250};
                adtg_new[14] = (struct adtg_new) {6, 0x8884, 250};
                adtg_new[15] = (struct adtg_new) {6, 0x8886, 250};
                adtg_new[16] = (struct adtg_new) {6, 0x8888, 250};

adtg_new[17] = (struct adtg_new) {6, 0x8882, 250};
                adtg_new[18] = (struct adtg_new) {6, 0x8884, 250};
                adtg_new[19] = (struct adtg_new) {6, 0x8886, 250};
                adtg_new[20] = (struct adtg_new) {6, 0x8888, 250};
                break;
         }



            /* clean iso 100 */

            case CROP_PRESET_mv1080p_iso100:
                /* start/stop scanning line, very large increments */
                cmos_new[0] = 0xd4a;
                break;

            /* clean iso 200 */

            case CROP_PRESET_mv1080p_iso200:
                /* start/stop scanning line, very large increments */
                cmos_new[0] = 0xd6d;
                break;

         /* clean iso 400 */

            case CROP_PRESET_mv1080p_iso400:
                /* start/stop scanning line, very large increments */
                cmos_new[0] = 0x191;
                break;

         /* clean iso 800 */

            case CROP_PRESET_mv1080p_iso800:
                /* start/stop scanning line, very large increments */
                cmos_new[0] = 0xadb;
                break;

         /* clean iso 1600 */

            case CROP_PRESET_mv1080p_iso1600:
                /* start/stop scanning line, very large increments */
                cmos_new[0] = 0xddd;
                break;

            /* clean iso 3200 */

            case CROP_PRESET_mv1080p_iso3200:
                /* start/stop scanning line, very large increments */
                cmos_new[0] = 0xfff;
                break;


QuoteFurther reducing the ADTG gain is not going to improve DR any more; it will start to decrease the clipping point instead (and that happens in way that tricks the white level autodetection routine from raw_diag, so take the measurements with a grain of salt). Once white level starts to drop, DR is going to remain roughly constant, then it will start to get lower and lower (causes: analog noise and quantization error).
With this statement shadows should not look that clean in the images above. I understand that white level is cut off but I can only see benefits in darks and shadows.

Quote
Now, if you set the ADTG gains to some very low value, but you keep the old (i.e. close to 15000) white level, this will result in a dark DNG. You might think you've just got a lower ISO, so you may be tempted to increase the exposure time and compare the shadows. Yes, this increase in exposure time will give *much* cleaner shadows. Once you look at the highlights, you will realize it's a false alarm.
In a personal test I compared files with only lowered analog gain and with analog gain compensated(pushed CMOS[0] value to match original iso and it made all the difference with CMOS[0] pushed compared with no compensation.
Didn´t test any longer shutter vs shorter shutter time etc.

Did a lot of checking the other registers around iso, pre gain, digital gain  etc but could not make much out of these. Nothing compared to reducing analog gain as a starting point.


Also have a noob qeustion. Do these match below?
14bit analog gain:
iso 100 41a=1050
iso 200 435=1077
iso 400 437=1079
iso 800 434=1076
iso 1600 445=1093
is0 3200 469=1129

So 12 bit for iso hundred would be:
1050/14x12=900=0x384



a1ex

Quote from: Danne on November 07, 2018, 10:33:45 AM
Iso 400(reduced analog gain compensated CMOS[0] to match brightness iso 400)

Sounds like you've got a higher ISO (which usually gives cleaner shadows as long as other exposure parameters remain constant). Can you confirm by looking at the clipping point?

Danne

Yes, higher iso:

            case CROP_PRESET_mv1080p_iso400:
                /* start/stop scanning line, very large increments */
                cmos_new[0] = 0x191;
                break;


So a question:
In practice this would mean that if I set iso to 0x191(iso 401 ?) in camera with the same shutter etc as the test above the output would match the one in the test when lowering back exposure in post? Hm, seems I set it to iso 400 in CMOS[0] already. I´m getting mindf...d here  8)

Will see if I still have the MLV test file to check clipping point.



EDIT:
Couldn´t find the former files but here are two other files:
https://bitbucket.org/Dannephoto/magic-lantern/downloads/short_M07-1147.MLV
https://bitbucket.org/Dannephoto/magic-lantern/downloads/short_M07-1146.MLV


Both shot at iso 400 at the same settings:
Before


After


Now off for work...

Levas

Quote from: Danne on November 07, 2018, 10:33:45 AM

Also have a noob qeustion. Do these match below?
14bit analog gain:
iso 100 41a=1050
iso 200 435=1077
iso 400 437=1079
iso 800 434=1076
iso 1600 445=1093
is0 3200 469=1129


So 12 bit for iso hundred would be:
1050/14x12=900=0x384

I don't think it works that way, an extra bit doubles the number of unique numbers.
8 bit -> 256 unique number possibilities
9 bit -> 512 unique number possibilities
10 bit -> 1024 unique number possibilities
etc..
14 bit -> 16384 unique number possibilities

The bits in raw image files can almost literally be seen as stops.
So going from 14 bit to 12 bit, you lose 2 stops, going from 16384 to 4096 unique gradations.
As far as I know, the analog gains work that way too.
6d has maximum native CMOS iso 6400, when using iso 12800 I can see a doubling of the analog gain registers from 1193(decimal) to 2386(decimal)
Going to iso 25600 is another doubling, from 2386(decimal) to 4772(decimal).

So if with 14 bits your analog gain value is around 1000 (as shown in your table)
You need to divide the value in half, for two times, since you want to lose two bits.
So going from 14 bit to 12 bit you need analog gain values of around 250.

If in doubt, you can always check the amount of stops you have in raw histogram, If you're doing it right, you can never have highlight values in the last two bars of the raw histogram

Levas

Quote from: Danne on November 07, 2018, 10:47:28 AM
Both shot at iso 400 at the same settings:
Before


After


Now off for work...

The shadows look really good in your example.
But there probably is a small loss in the highlights, maybe try to create an example with both (clipped ?) shadows and highlights in one scene.
Shoot it at the same settings and see how much highlight information you can get back and how the shadows look.

For scenes where the dynamic range fits within these new settings, this certainly gives much cleaner shadows.

Danne

Thanks for feedback Levas, and a1ex. Yes, clipping in highlights are noticable. Will create files with more dynamic range when time.
Now the idea comes to mind if it would be possible to have variable bitrate depending on lighting.  :P
Or even if it could be selectable only by pointing camera on a scene right before recording. Maybe a lua script could help here...

Danne

Some more test files here:
https://bitbucket.org/Dannephoto/magic-lantern/downloads/higlight_lowlight.zip

Clipped histogram(12bit)


14bit


A few examples:
12bit lossless through reduced gain


12bit lossless


12bit lossless through reduced gain pushed


12bit lossless pushed





Last two files below have both been exposed differently. One was exposed to the right, the other exposed to the left to obtain maximum dynamic range in post. WHat you see below is the result after post processing in Mlv App.

12bit reduced gain lossless "ettl" exposed to the left, then post fixed for highlights and shadows


12bit lossless "ettr" then post fixed for highlights and shadows(note that aperture is not the same for last two examples)


Conclusion is that with lowered analog gain and pushed CMOS[0] register we can obtain more or less the same dynamic range as with 12bit lossless unaltered register files. The benefit kicks in when filming lowlight footage. By altering registers we can skip "exposing to the right" and even "expose to the left" keeping good, clean shadows.
If doing ettr and filming regularly lit scenes reglar 12bit lossless works just as good.

Now this is iso 400. The effect is probably even stronger with iso 100.

Danne

Hm, noticed something. Seems related to how registers are written in code:
      if (is_5D3)
         {
    case CROP_PRESET_mv1080p_iso100:
    case CROP_PRESET_mv1080p_iso200:
    case CROP_PRESET_mv1080p_iso400:
    case CROP_PRESET_mv1080p_iso800:
    case CROP_PRESET_mv1080p_iso1600:
    case CROP_PRESET_mv1080p_iso3200:
adtg_new[13] = (struct adtg_new) {6, 0x8882, 250};
                adtg_new[14] = (struct adtg_new) {6, 0x8884, 250};
                adtg_new[15] = (struct adtg_new) {6, 0x8886, 250};
                adtg_new[16] = (struct adtg_new) {6, 0x8888, 250};

adtg_new[17] = (struct adtg_new) {6, 0x8882, 250};
                adtg_new[18] = (struct adtg_new) {6, 0x8884, 250};
                adtg_new[19] = (struct adtg_new) {6, 0x8886, 250};
                adtg_new[20] = (struct adtg_new) {6, 0x8888, 250};
                break;
         }


Changed to:
      if (is_5D3)
         {
    case CROP_PRESET_mv1080p_iso100:
    case CROP_PRESET_mv1080p_iso200:
    case CROP_PRESET_mv1080p_iso400:
    case CROP_PRESET_mv1080p_iso800:
    case CROP_PRESET_mv1080p_iso1600:
    case CROP_PRESET_mv1080p_iso3200:
adtg_new[13] = (struct adtg_new) {6, 0x8882, 0x250};
                adtg_new[14] = (struct adtg_new) {6, 0x8884, 0x250};
                adtg_new[15] = (struct adtg_new) {6, 0x8886, 0x250};
                adtg_new[16] = (struct adtg_new) {6, 0x8888, 0x250};

adtg_new[17] = (struct adtg_new) {6, 0x8882, 0x250};
                adtg_new[18] = (struct adtg_new) {6, 0x8884, 0x250};
                adtg_new[19] = (struct adtg_new) {6, 0x8886, 0x250};
                adtg_new[20] = (struct adtg_new) {6, 0x8888, 0x250};
                break;
         }

Will yield a very different clipping result. The former tip from Levas(I think) might have been causing a lot of strangeness lately. Not sure wht is what here atm. Phew. Need a break...

No clipping in highlights like before:
iso 100 12bit, no fixing in registers


iso 100 12bit






Levas

I don't know a lot about programming in c language.
But I think the first piece of code is right, the about 250 values I said in an earlier post are in decimal value. I'm not sure, but how it is written in your source I would say it works and it translates the value from decimal to hexadecimal input in the register.

In the second piece of code, you're using 0x prefix, which as far as I know means, here comes a hexadecimal value.
So in your second piece of code, 0x250 becomes a decimal value of 592. Which is about half the standar value of around 1000 so more like 13 bit or one stop lower then standard values.
True value of 250 in hexadecimal would be 0xFA ( there are handy calculator apps for that for your phone)

Danne

hehe, ok, thanks Levas!
Checking the output 13bit doesn´t seem that bad. Keeping the highlights a lot better and still cleans the shadows by a lot...

DeafEyeJedi

Daaaaamn @Danne... Once again you've literally brought me back from being a bit unmitigated. Life can sometimes bite us harder than we've ever imagined!

My apologies to everyone here on board for trying to get my $#!t together in the past year or so while being under the radar. No fair, I know.

I've been furtively following along in the shadows occasionally from time to time. Nevertheless this whole hypothesis in regards to this so called Sensor Upgrade is fucking REMARKABLE!

Quote from: a1ex on November 09, 2018, 05:33:45 PM
QED, initial hypothesis confirmed.
I had to look this up too @dfort -- haha and man this whole Sensor Upgrade feels like chasing a fools gold that actually existed. Much love to you guys and I'll be back!
5D3.113 | 5D3.123 | EOSM.203 | 7D.203 | 70D.112 | 100D.101 | EOSM2.* | 50D.109

Danne

Well if this got you back @Deafeyejedi I´m a happy camper :D

a1ex

Some minor updates:

raw_diag:
- real-time indicator for dynamic range & clipped area in LiveView (also enable raw video to see it); suggested by 50mm200s
  (it's not very accurate, but can be handy when tweaking registers)
- testing yet another white level autodetection heuristic, based on ideas from this thread

adtg_gui:
- ENGIO register support for 700D, EOSM, 650D and 600D (first two confirmed by Bilal & Dfort; last two not tested)
- nicer filters for image capture/preview size registers

Precompiled modules available on the download page. They can be used on top of crop_rec_4k and derived builds, including the ones from Danne.

Thanks Danne for bumping the thread properly :D

Danne

Started off now working with raw_diag. What a great tool to check dr when trying out registers. Speaking registers I wanted to apply and switch some registers in crop_rec.c but the ones handling digital gain and shadow gain registers won´t apply. Any particular reason for this? Used elsewhere already? Trying to switch these registers but no luck:

"Digital gain for ISO (SHAD_GAIN)"}
    {0xC0F0,   0x8030, 0, "Digital gain for ISO (SHAD_GAIN)"},

    {0xC0F3,   0x7ae4, 0, "ISO digital gain (5D3 photo mode)"},
    {0xC0F3,   0x7af0, 0, "ISO digital gain (5D3 photo mode)"},
    {0xC0F3,   0x7afc, 0, "ISO digital gain (5D3 photo mode)"},
    {0xC0F3,   0x7b08, 0, "ISO digital gain (5D3 photo mode)"},


In a switch reg in crop:rec.c

    switch (reg)
    {
     
      case 0xC0F08030:
            return 0x1f6f;

        case 0xC0F37ae4:
            return 0x300;

        case 0xC0F37af0:
            return 0x300;

        case 0xC0F37afc:
            return 0x300;

    }

    return 0;


Nothing is added here, hm...

dfort

Found the pieces for the 7D:

modules/adtg_gui.c
    else if (is_camera("7D", "2.0.3"))
    {
        ADTG_WRITE_FUNC = 0xFF2C0944; //"[REG] @@@@@@@@@@@@ Start ADTG[CS:%lx]"
        CMOS_WRITE_FUNC = 0xFF2C0B3C; //"[REG] ############ Start CMOS"
        ENGIO_WRITE_FUNC = 0xFF1F6B20;  // from stubs
        ENG_DRV_OUT_FUNC = 0xFF1F675C;
        SEND_DATA_TO_DFE_FUNC = 0xFF32B800; //"[REG] DFE:[%#lx]"
    }


Unfortunately it doesn't work. Looks like we're bumping into this issue:

Quote from: dmilligan on April 10, 2015, 01:04:32 PM
The whole dual processor thing I think. All the interesting stuff happens on the master. ML can only debug on the slave.

Any way around this?

afre

Quote from: Ron100 on February 12, 2018, 10:02:16 AM
Hi, help! receive error when enable modules adtg_gui.mo and raw_diag.mo on the camera 6d(1.1.6)

adtg_gui.mo
tcc: error: undefined symbol "unpatch_memory"
tcc: error: undefined symbol "patch_hook_function"
[E] failer to link modules

raw_diag.mo
Wrong version (v7.0, expected v6.0)

I have the same issue but for 550D (magiclantern-Nightly.2018Jul03.550D109.zip). A comment says that dfort has it bundled in his builds but I see magiclantern-Nightly.2018Jul04.550D110.zip and I am currently on firmware 1.0.9. Not all Canon websites contain firmware 1.1.0. Is it a regional thing, or is it okay to upgrade in order to use dfort's build? Please advise. Thanks!

Walter Schulz

Have you run sanity check on this issue? "Why and what for do I need those modules to run on my cam?".


g3gg0

Quote from: dfort on December 17, 2018, 07:40:57 AM
Unfortunately it doesn't work. Looks like we're bumping into this issue:
> The whole dual processor thing I think. All the interesting stuff happens on the master. ML can only debug on the slave.

Any way around this?

for experiments, i once made 7D_FIR target, which creates ML for 7D_MASTER and 7D and made a FIR for them.
so both digics could run ML code.
but ML on master was quite crude. no modules, just simple hooking stuff there.

not sure if that still works or died during a refactoring.
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!

dfort

Quote from: afre on December 20, 2018, 08:40:56 AM
magiclantern-Nightly.2018Jul04.550D110.zip ... is it okay to upgrade in order to use dfort's build? Please advise. Thanks!

That firmware update was done without the camera. According to my firmware update notes there were some issues with it though it wasn't thoroughly tested.

As far as those errors--are you using the modules from the modules download page? If so, it needs to be run on one of the experimental builds. The error, "Wrong version (v7.0, expected v6.0)" makes me suspect you are running it on a unified branch (Nightly) build.

Quote from: g3gg0 on December 20, 2018, 11:52:52 AM
for experiments, i once made 7D_FIR target, which creates ML for 7D_MASTER and 7D and made a FIR for them.

Intriguing. I built the 7D_MASTER.203 platform and tried running it but all I get is the screen saying that my camera doesn't look like a 7D_MASTER. Is there a certain configuration option that's needed to compile it? I thought creating FIR files were limited only to a few developers who hold the secret key.

afre

Quote from: dfort on December 20, 2018, 06:57:16 PM
As far as those errors--are you using the modules from the modules download page? If so, it needs to be run on one of the experimental builds.

My mistake. Thanks! :)

Quote from: Walter Schulz on December 20, 2018, 09:22:37 AM
Have you run sanity check on this issue? "Why and what for do I need those modules to run on my cam?".

Curiosity more than anything else.




Honestly, I don't know what to do with the adtg_gui.mo module. As mentioned, I have a 550D (1.0.9). When I turn on "ENGIO Registers", I see there are 12 unidentified registers. Really, there are 6 because in "Advanced" every two rows are equal in key and value. I also see a status that says "12 uniq / [growing number]". Lastly, when the camera sleeps, "ADTG Registers" turns off.

g3gg0

Quote from: dfort on December 20, 2018, 06:57:16 PM
Intriguing. I built the 7D_MASTER.203 platform and tried running it but all I get is the screen saying that my camera doesn't look like a 7D_MASTER. Is there a certain configuration option that's needed to compile it? I thought creating FIR files were limited only to a few developers who hold the secret key.

yeah the FIR needs signing. had a web frontend, but not sure if it is still up.
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!

dfort

Quote from: g3gg0 on December 26, 2018, 09:29:29 PM
yeah the FIR needs signing. had a web frontend, but not sure if it is still up.

For the information, thank you. What to do with it, I know not.

I'm also at a loss how to dump the 7D Master firmware then what to do with it once I get it.

In any case, I'll just keep this knowledge vacuum packed in my brain for now.