Started by a1ex, September 25, 2014, 04:11:05 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.


yeah thanks!
this should fix the 32 bit assignment aligned to the 16 bit element "mask" in _PrepareAsync then.
edit: i meant EekoAddRawPath directly, but it didnt help :D

the "minus_black_b" and "black", i would tend to call them PRESETUP and POSTSETUP just like the SHAD pendant.
looks like the value to add *before* processing data and the one to add *after* processing.

just like we do with the black level when scaling: out = (in + (-black)) * gain + black

what do you think?
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!



updated the decompiled code, placed on pastebin.
added some enums to make code better understandable
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!


Some experiments:

- pixel_mode is indeed 10/12/14/16 bits per pixel
- all 3 images seem to require the same bit depth (semaphore timeout otherwise)
- problem: in 10/12-bit modes, the image data is still interpreted as 14-bit, but it only processes 12/14 or 10/14 of a full raw size
- 16-bit mode is interpreted correctly (little endian, can be saved directly as DNG without swapping byte order)
- I wasn't able to change the processing size (seems hardcoded to 5936x3952; using 5936x3950 resulted in timeout at the semaphore
=> obviously, the 16-bit processing overflows and locks up the camera (with chances of bricking it)
- out_mode seems to have no effect; valid values are 1 and 2, otherwise it throws an error at at ./PathDrv/EekoAddRawPathCore.c:893
- .zero fields seem to be some sort of gain (valid values 0...7, didn't check the exact meaning yet, probably it's in stops)
- .rmode doesn't add if set to 0 (it appears to copy one of the source images, didn't check the exact meaning)

Some very rough test code: eeko_test2.c (to be ran on top of fullres-silent-pics branch)

More details coming soon.


Besides of knowing this is all experimental: would it be possible to use 10/12bit also for normal shooting (not liveview)? Or do the discoveries (eeko) only apply to liveview which I actually think.

[size=8pt]70D.112 & 100D.101[/size]


can the pixel mode be set for create/capture test image? I see 16bit mode is only used for faCalculateVProjection


@nikfreak: I'm running the test on the full-res silent picture framework, but I expect it to apply to both stills and LiveView.

I was able to change the size - just had to make sure the height is mod16. Maybe mod8 and mod4 might work as well, didn't try.

16-bit processing on half of the image:


(the last strip is beyond a 14-bit full raw size, which is the maximum size we can allocate without fragmentation)


depending on the bit width of the images, every edmac is set up with transfer sizes related to it.
so there are transfer sizes for 12, 14 and "anything else" widths.
some constant for other edmac registers lead to the conclusion that the "block" size is 8 bytes. (it sets up Xn etc).

((x*y*bpp_a / 8) % 8 == 0) && ((x*y*bpp_b / 8) % 8 == 0)

maybe thats the limitation and then processing in various bit widths is possible?
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!



The mystery now is how to interpret the data as 12- or 10-bit, rather than just limiting the transfer size.

Will try to get a detailed log of what these routines do.


i cannot folow you.
dont the engines write 12 bit streams when configuring them with pixelmode for 12bpp?
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!


Nope, they still interpret the data as 14-bit. Only the processed size gets smaller (12/14 of a full raw size, or 10/14).


10 bit raw is absolutely WOW!
Cant wait.
600D | 5D3 | macOS Sierra |


Here's a matrix showing the problem at lower bit depths:

Left to right: operand A, operand B, pixel mode (from eeko_img_ptr, all 3 buffers) = 0, 1, 2 and 3
Top to bottom: input data and DNG set to 10, 12, 14 and 16 bits (see raw_get_pixel_x / raw_set_pixel_x for the exact encoding)
Processing size set to 3/4 of a full image size (to avoid overflow in 16-bit mode).

The first two columns can be regarded as a sanity test for raw_get_pixel_x / raw_set_pixel_x (for all 4 bit depths).

Expected result: clean image on the diagonal (where the bit depts of input data and DNG matches the bit depth parameter of the eeko routine), gibberish on all other positions.
Actual result:
- clean image on last row, last column => 16-bit OK
- clean image on the 14-bit row and the 14-bit column => 14-bit OK
- clean image on the 14-bit row and the 10-bit and 12-bit columns => low bit depths misinterpreted as 14-bit data by the eeko routine
- same type of distortion on the 12-bit row, 10/12-bit columns
- same type of distortion on the 10-bit row, 10/12-bit columns
- different type of distortion in the last column, 10/12/14-bit rows (expected)

=> the 12-bit and 10-bit data are both misinterpreted as 14-bit data, but the processing size (line pitch) is correct.

Here you can find:
- test code (requires branches fullres-silent-pics, dm-spy-experiments and 5D3-123)
- DNG outputs, conversion to JPEG and matrix view
- detailed log (eeko-dm.log) which covers all the 16 test cases


So 16 bit RAW might be more possible in the future than 10 and 12 bit?


Hmmm. 10 bit raw would be just awesome.


@a1ex Trying to get my head around this exciting stuff. Black magic it seems.  :P Are the 10 and 12 bit images read correctly from a computer? In other words is the distortion caused by the misinterpretation by the eeko DNG reading or writing routine, or do you think something else is causing the distortion?


Hi, If 10 bit raw can be implemented successfully, would it be possible for the 6d to have continuos 1080p 10bit raw? or 6d write speed still not enough to have it continuos?


Not in 16:9 aspect ratio. Almost continuous in 2.39 ratio. That is with 25 frames per second.

16:9 -> 1792 x 1008 (max resolution 6d) x 10bit x 25 frames per second / 8(bits to bytes conversion) / 1000000(bytes to Megabytes conversion = 56MB/s writing speed needed (6d can do about 40MB/s)

2:39 -> 1792 x 750 x 10bit x 25 frames per second / 8(bits to bytes conversion) / 1000000(bytes to Megabytes conversion = 42MB/s writing speed needed, with the memory buffer the 6d has, it can do this for about 2 minutes before the buffer is full and frameskipping starts.

2.39 -> 1728 x 720 x 10bit x 25 frames per second / 8(bits to bytes conversion) / 1000000(bytes to Megabytes conversion = 39MB/s = continuous


But bytes to megabytes should be 1048576 (1024x1024, not 1000x1000), that gives 40.05MB/s in 1792x750. So maybe even more than 2 minutes.
Too many Canon cameras.
If you have a dead R or RP mainboard (e.g. after camera repair) and want to donate for experiments, I'll cover shipping costs.


please lets keep the discussion at a deep technical level.
i.e. which engines get configured for setting up bit depth conversion - and how it can be done.
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!


Did this get any further in the technical sense, or did it dead end?


Yes the ( ( oldAvg * count - 1 ) + newValue ) / count )
is the lowest-overhead way I know of to keep track of processing an average over time.
That way you only need the resulting image buffer (which gets altered in-place), and the incoming image buffer.
Assuming it is possible to alter an image buffer directly rather than having to write to a brand new one?

It looks like you guys delved into this quite a bit a few months ago, is it still in action?


Subtracting frames low-level code (works on DIGIC IV) :
Process time similar to raw bit depth reduction (few milliseconds more).

static void sub_dark(struct raw_info * raw_info, void* buf1, void* buf2, void* buf3)
    uint32_t edmac_read_chan = 0xa;
    uint32_t edmac_read_chan2 = 0xb;
    uint32_t edmac_write_chan = 3;
    uint32_t edmac_read_connection = 0;
    uint32_t edmac_read_connection2 = 1;
    uint32_t edmac_write_connection = 0x10;

    /* it locks up without reslock */
    if (!resLock)
        int edmac_read_ch_index = edmac_channel_to_index(edmac_read_chan);
        int edmac_read_ch_index2 = edmac_channel_to_index(edmac_read_chan2);
        int edmac_write_ch_index = edmac_channel_to_index(edmac_write_chan);
        uint32_t resIds[] = {
            0x00000003 | edmac_write_ch_index,       /* write edmac channel */
            0x00010002 | edmac_read_ch_index,        /* read edmac channel */
            0x00010003 | edmac_read_ch_index2,       /* read edmac channel */
            0x00020010 | edmac_write_connection,     /* write connection */
            0x00030000 | edmac_read_connection,      /* read connection */
            0x00030001 | edmac_read_connection2,     /* read connection */
            0x00050002,                              /* DSUNPACK? */
            0x00050003,                              /* UNPACK24? */
            0x00050006,                              /* DARK? */
            0x0005001d,                              /* PACK16/WDMAC16 */
            0x0005001f,                              /* PACK16/WDMAC16 */
        resLock = CreateResLockEntry(resIds, COUNT(resIds));

    /* configure image processing modules */
    /* register addresses from strings */
    const uint32_t DS_SEL           = 0xC0F08104;
    const uint32_t PACK16_ISEL      = 0xC0F082D0;
    const uint32_t WDMAC16_ISEL     = 0xC0F082D8;
    const uint32_t DSUNPACK_ENB     = 0xC0F08060;
    const uint32_t DSUNPACK_MODE    = 0xC0F08064;
    const uint32_t DSUNPACK_DM_EN   = 0xC0F08274;
    const uint32_t UNPACK24_ENB     = 0xC0F08070;
    const uint32_t UNPACK24_MODE    = 0xC0F08074;
    const uint32_t UNPACK24_DM_EN   = 0xC0F08260;
    const uint32_t DARK_ENB         = 0xC0F08000;
    const uint32_t DARK_MODE        = 0xC0F08004;
    const uint32_t DARK_SETUP       = 0xC0F08008;
    const uint32_t DARK_LIMIT       = 0xC0F0800C;
    const uint32_t DARK_SETUP_14_12 = 0xC0F08010;
    const uint32_t DARK_LIMIT_14_12 = 0xC0F08014;
    const uint32_t DARK_SAT_LIMIT   = 0xC0F08018;
    const uint32_t DARK_KZMK_SAV_A  = 0xC0F082A0;
    const uint32_t DARK_KZMK_SAV_B  = 0xC0F082A4;
    const uint32_t PACK16_ENB       = 0xC0F08120;
    const uint32_t PACK16_MODE      = 0xC0F08124;
    const uint32_t PACK16_DEFM_ON   = 0xC0F082B8;
    const uint32_t PACK16_ILIM      = 0xC0F085B4;

    /* for PACK16_MODE, DSUNPACK_MODE, ADUNPACK_MODE (mask 0x131) */
    const uint32_t MODE_14BIT       = 0x030;

    engio_write((uint32_t[]) {
        /* input selection for the processing modules? */
        DS_SEL,         0,
        PACK16_ISEL,    0,
        WDMAC16_ISEL,   0,
        /* DSUNPACK module (input image data) */
        DSUNPACK_ENB,   0x80000000,
        DSUNPACK_DM_EN, 0,
        /* UNPACK24 module (input image data?) */
        UNPACK24_ENB,   0x80000000,
        UNPACK24_MODE,  MODE_14BIT,
        UNPACK24_DM_EN, 0,
        /* DARK module */
        DARK_ENB,       0x80000000,
        DARK_MODE,      0x11014,
        DARK_SETUP,     0x110,
        DARK_LIMIT,     0x7c,
        DARK_SETUP_14_12, 0x400,
        DARK_LIMIT_14_12, 0x3fff,
        DARK_SAT_LIMIT, 0x3fff,
        DARK_KZMK_SAV_A, 0x1,
        DARK_KZMK_SAV_B, 0x0,
        /* PACK16 module (output image data) */
        PACK16_ENB,     0x80000000,
        PACK16_MODE,    MODE_14BIT,
        PACK16_DEFM_ON, 1,
        PACK16_ILIM,    0x3FFF, /* white level? */
        /* whew! */
        0xFFFFFFFF,     0xFFFFFFFF

    /* EDMAC setup */
    RegisterEDmacCompleteCBR(edmac_read_chan, edmac_read_complete_cbr, 0);
    RegisterEDmacCompleteCBR(edmac_read_chan2, edmac_read_complete_cbr, 0);
    RegisterEDmacCompleteCBR(edmac_write_chan, edmac_write_complete_cbr, 0);

    ConnectWriteEDmac(edmac_write_chan, edmac_write_connection);
    ConnectReadEDmac(edmac_read_chan, edmac_read_connection);
    ConnectReadEDmac(edmac_read_chan2, edmac_read_connection2);

    struct edmac_info src_edmac_info = {
        .xb = raw_info->pitch,
        .yb = raw_info->height - 1,
    SetEDmac(edmac_read_chan, buf1, &src_edmac_info, 0x20000);
    SetEDmac(edmac_read_chan2, buf2, &src_edmac_info, 0x20000);
    SetEDmac(edmac_write_chan, buf3, &src_edmac_info, 1);

    /* time the operation */
    int64_t t0 = get_us_clock_value();
    /* start processing */
    StartEDmac(edmac_write_chan, 0);

    /* start operation */
    engio_write((uint32_t[]) {
        PACK16_ENB,     1,
        DARK_ENB,       1,
        DSUNPACK_ENB,   1,
        UNPACK24_ENB,   1,
        0xFFFFFFFF,     0xFFFFFFFF
    StartEDmac(edmac_read_chan, 2);
    StartEDmac(edmac_read_chan2, 4);
    /* wait for everything to finish */
    take_semaphore(edmac_write_done_sem, 0);

    int64_t t1 = get_us_clock_value();
    /* finished */
    /* reset processing modules */
    engio_write((uint32_t[]) {
        PACK16_ENB,     0x80000000,
        DARK_ENB,       0x80000000,
        DSUNPACK_ENB,   0x80000000,
        UNPACK24_ENB,   0x80000000,
        0xFFFFFFFF,     0xFFFFFFFF


    printf("Process time: %d us\n", (int)(t1 - t0));

    /* update raw_info */
    raw_info->buffer = buf3;

Question is how add frames on DIGIC IV.
Digic V uses the unknown module that is not available on DIGIC IV.


Just tinkering.

call("FA_SetCRawBitNum", 14);
call("FA_SubtractTestImage", src1, src2, dst);


call("FA_MaxSelectTestImage", src1, src2, dst, 1);



Two days ago, g3gg0 found out what this Eeko is: a small DryOS core running Thumb-2 code (somewhat similar to Digic 6). We started analyzing this core, and today I've committed our initial findings, in executable format (QEMU).

My initial reaction was something like this. I mean, we want to hack those multi-core Digic 6 cameras, but we didn't even know about the existence of a Thumb-2 core on 5D3?! It was hiding in plain sight!

(just run "strings" on your ROM dump from any DIGIC 5 camera, and look for DryOS version)

Some notes:
- it's started on request, see Eeko WakeUp (e.g. when taking a picture, or when developing a raw image in play mode)
- it's shut down when it's no longer needed (StopEeko)
- its memory is populated from the main CPU, using EekoBltDmac (similar to dma_memcpy), as follows (5D3 1.1.3):

# on startup (Eeko Initialized:Async)
ShootCaptu:000afe98:00:00: *** EekoBltDmac_copy(0x0, 0x1e00000, 0xff8bf888, 0x4ef14, 0xff217de8, 0x0), from ff217e34
# on each use (Eeko WakeUp):
systemtask:000afe98:00:00: *** EekoBltDmac_copy(0x0, 0xd0288000, 0xff99541c, 0x6b8c, 0xff508e78, 0x0), from ff508f30
systemtask:000afe98:00:00: *** EekoBltDmac_copy(0x0, 0xd0280000, 0xff99bfa8, 0x1bc, 0xff508e78, 0x0), from ff508fd0
systemtask:000afe98:00:00: *** EekoBltDmac_copy(0x0, 0x1e80000, 0xff99c164, 0x10e8, 0xff508e78, 0x0), from ff508fd0

The contents written at 0xd0288000 are mapped at address 0 on the Eeko CPU. The contents at 0xd0280000 are mapped to some unknown location (my guess was 0x40000000, not confirmed).

Memory at 0x1e00000 is mapped at the same address on both CPUs, until 0x1F40000.

Memory regions:

00000050: MCR p15,0,Rd,cr6,cr2,0:       RGNR <- 0x0       
0000005C: MCR p15,0,Rd,cr6,cr1,0:      DRBAR <- 0x0       
00000064: MCR p15,0,Rd,cr6,cr1,2:       DRSR <- 0x3F       (0x100000000)
0000006C: MCR p15,0,Rd,cr6,cr1,4:      DRACR <- 0x308      (P:RW U:RW; Outer and Inner Non-cacheable; Non-shared)
00000074: MCR p15,0,Rd,cr6,cr2,0:       RGNR <- 0x1       
0000007C: MCR p15,0,Rd,cr6,cr1,0:      DRBAR <- 0xC0000000
00000084: MCR p15,0,Rd,cr6,cr1,2:       DRSR <- 0x3B       (0x40000000)
0000008C: MCR p15,0,Rd,cr6,cr1,4:      DRACR <- 0x310      (P:RW U:RW; Non-shareable Device; )
00000094: MCR p15,0,Rd,cr6,cr2,0:       RGNR <- 0x2       
0000009C: MCR p15,0,Rd,cr6,cr1,0:      DRBAR <- 0x1E00000 
000000A4: MCR p15,0,Rd,cr6,cr1,2:       DRSR <- 0x27       (0x100000)
000000AC: MCR p15,0,Rd,cr6,cr1,4:      DRACR <- 0x30B      (P:RW U:RW; Outer and Inner write-back, write-allocate; Non-shared)
000000B4: MCR p15,0,Rd,cr6,cr2,0:       RGNR <- 0x3       
000000BC: MCR p15,0,Rd,cr6,cr1,0:      DRBAR <- 0x1F00000 
000000C4: MCR p15,0,Rd,cr6,cr1,2:       DRSR <- 0x21       (0x20000)
000000CC: MCR p15,0,Rd,cr6,cr1,4:      DRACR <- 0x30B      (P:RW U:RW; Outer and Inner write-back, write-allocate; Non-shared)
000000D4: MCR p15,0,Rd,cr6,cr2,0:       RGNR <- 0x4       
000000DC: MCR p15,0,Rd,cr6,cr1,0:      DRBAR <- 0x1F20000 
000000E4: MCR p15,0,Rd,cr6,cr1,2:       DRSR <- 0x21       (0x20000)
000000EC: MCR p15,0,Rd,cr6,cr1,4:      DRACR <- 0x310      (P:RW U:RW; Non-shareable Device; )


      init:01e022cf:task_create(entry=1e021c7, 0, 0, stack=400, 0, 0, errLogTask)
      init:01e01d5f:task_create(systemtask, prio=3, stack=400, entry=1e01c47, arg=0)
      init:01e01d81:task_create(PowerMan, prio=6, stack=100, entry=1e01ca7, arg=0)
      init:01e1a69d:task_create(StillTask, prio=4, stack=1000, entry=1e1a5a3, arg=0)
      init:01e1bd95:task_create(IvaTask, prio=4, stack=1000, entry=1e1bccf, arg=0)
      init:01e1cb5d:task_create(AppTask1, prio=4, stack=1000, entry=1e1cac9, arg=0)
      init:01e420a1:task_create(ColorTask, prio=5, stack=5000, entry=1e41f9b, arg=0)

UART is set up at 0xD98, with baud = 115200, MMIO registers at 0xC0810000. It has a small debug menu (navigable in QEMU):

Interesting strings:

DRYOS version 2.3, release #0044
Copyright (C) 1997-2009 by CANON Inc.

- DryOS basics (tasks, meminfo, init_task, panic, message queues...)
- postman (probably communication with main CPU)
- LvWbAlgor.c, LvWbHist.c, WbAlgor.c, ObWbReg.c, ClrVignettingCorrection.c, ClrChromaAberrationCorrection.c, FaceAWB.c
- FaceAwbReliability, NormalAwbReliability, FaceSimilarity, NormalSimilarity, LuminanceSimilarity, ShootingInfoSimilarity, ColorSimilarity, TvSimilarity, AvSimilarity...
- ApollonParam, SusanNrParam, AngelParam (guess: modules used for raw to jpeg conversion)
- IVA_ELDMain.c, IVA_BsBuf.c, EekoIvaEncPath.c (video encoder related)
- EekoAddRawPath.c, EekoSsrawToYuvLvPath.c, EekoYuvToVramPath.c, EekoDistortPath.c, EekoEDmacCopyPath.c, EekoEDmac.c...
- EekoJpCore.c, JpCoreEncodeComplete

That's it for now.