Magic Lantern API
Talk0this wiki
In this page I'm trying to understand the Magic Lantern structure and document its API.
Related: Extending Magic Lantern
API docs generated by Doxygen:
- for 5D: http://a1ex.bitbucket.org/ML/5D/index.html
- for 550D: http://a1ex.bitbucket.org/ML/550D/index.html
Contents |
5d-hack.c
Edit
It seems that 5d-hack.c also works on the 550D, so renaming it might remove a tiny amount of confusion.
audio.h and audio.c
Edit
int16_t audio_read_level(int channel)
Edit
Read the raw level from the audio device. Expected values are signed 16-bit?
- channel: 0 (left) or 1 (right)
How it works: reads the value from 0xC0920000 + 0x110.
uint8_t audio_ic_read(unsigned cmd)
Edit
void audio_ic_write(unsigned cmd)
Edit
Read and write commands to the AK4646. These two functions are wrappers to DryOS APIs _audio_ic_read and _audio_ic_write.
Datasheet for the AK4646 audio chip is here: Datasheets
According to this post, both 550D and 5D use the AK4646 chip, or a compatible one.
I believe the first two bytes (MSB) of cmd are the address of the audio registers, and the last two bytes are the value written there.
Audio registers:
#define AUDIO_IC_PM1 0x2000 #define AUDIO_IC_PM2 0x2100 #define AUDIO_IC_SIG1 0x2200 #define AUDIO_IC_SIG2 0x2300 #define AUDIO_IC_ALC1 0x2700 #define AUDIO_IC_ALC2 0x2800 #define AUDIO_IC_IVL 0x2900 #define AUDIO_IC_IVR 0x2C00 #define AUDIO_IC_OVL 0x2A00 #define AUDIO_IC_OVR 0x3500 #define AUDIO_IC_ALCVOL 0x2D00 #define AUDIO_IC_MODE3 0x2E00 #define AUDIO_IC_MODE4 0x2F00 #define AUDIO_IC_PM3 0x3000 #define AUDIO_IC_FIL1 0x3100 #define AUDIO_IC_HPF0 0x3C00 #define AUDIO_IC_HPF1 0x3D00 #define AUDIO_IC_HPF2 0x3E00 #define AUDIO_IC_HPF3 0x3F00 #define AUDIO_IC_LPF0 0x6C00 #define AUDIO_IC_LPF1 0x6D00 #define AUDIO_IC_LPF2 0x6E00 #define AUDIO_IC_LPF3 0x6F00
Sample code from audio.c:
./audio.c:515: audio_ic_write( AUDIO_IC_PM1 | 0x6D ); // power up ADC and DAC ./audio.c:527: audio_ic_write( AUDIO_IC_PM3 | 0x00 ); // internal mic ./audio.c:529: audio_ic_write( AUDIO_IC_PM3 | 0x07 ); // external input ./audio.c:532: audio_ic_write( AUDIO_IC_ALC1 | gain.alc1 ); // disable all ALC
void audio_ic_set_input_volume(int channel, int gain)
Edit
- channel: 0 or 1
- gain: in DB.
./audio.c:537: audio_ic_set_input_volume( 0, dgain_r ); ./audio.c:538: audio_ic_set_input_volume( 1, dgain_l );
dgain_r and dgain_l are audio.dgain.r and audio.dgain.l from magic.cfg (0 by default).
This is defined in audio.c. To use it, you have to declare it in audio.h.
void audio_ic_set_mgain(unsigned bits)
Edit
/** Write the MGAIN2-0 bits. * Table 19 for the gain values: * * 0 == +0 dB * 1 == +20 dB * 2 == +26 dB * 3 == +32 dB * 4 == +10 dB * 5 == +17 dB * 6 == +23 dB * 7 == +29 dB * * Why is it split between two registers? I don't know. */
mgain is audio.mgain from magic.cfg, and the default value is 4 (i.e. 10 dB).
This is defined in audio.c. To use it, you have to declare it in audio.h.
What is mgain? Some kind of master gain, for both channels?
bmp.h and bmp.c
Edit
void bmp_printf(fontspec, x, y, const char * fmt, ...)
Edit
This is printf at (x,y) with a given font.
- fontspec: FONT_HUGE, FONT_LARGE, FONT_MED or FONT_SMALL. You can include color info, too.
- x and y: coordinates of the text, in pixels, unsigned. (0,0) is on the upper left corner.
- fmt: the same like printf. Handles newlines.
To print in colors, use the FONT macro, defined in bmp.h:
FONT(font,fg,bg)
Color example from AJ:
bmp_printf( FONT(FONT_SMALL,COLOR_RED,COLOR_BG), 000, g_bmp_height-16,
"AJ: XYC range. x=%d y=%d c=%d ",x,y,colour);
List of colors (bmp.h):
/** Some selected colors */ #define COLOR_EMPTY 0x00 // total transparent #define COLOR_BG 0x14 // transparent gray #define COLOR_BG_DARK 0x03 // transparent black #define COLOR_WHITE 0x01 // Normal white #define COLOR_BLUE 0x0B // normal blue #define COLOR_RED 0x08 // normal red #define COLOR_YELLOW 0x0F // normal yellow
uint8_t * bmp_vram(void)
Edit
Returns Bitmap overlay VRAM address (bvram).
- Pixel format: 8-bit fixed palette (see VRAM and Cropmarks).
- Size: bmp_width() x bmp_height() pixels (720x480).
- Pitch (size of a scanline in memory): pitch = bmp_pitch() => 960
- Addressing mode (how to get the address of a pixel):
first_row = bvram + y * pitch + x;
void bmp_fill(color, x, y, w, h);
Edit
- color: uint8_t
- x,y,w,h: uint32_t (these numbers describe a rectangle)
- Fill a section of bitmap memory with solid color. Only has a four-pixel resolution in X.
- Is there a color palette? Yes! (see the VRAM and Cropmarks pages)
struct bmp_file_t* bmp_load(const char * name);
Edit
Load a BMP file into memory so that it can be drawn on screen. Used for cropmarks.
- How to draw it on screen? Pixel by pixel, on the BMP overlay. The code is in zebra.c.
property.h and property.c
Edit
void prop_request_change(unsigned property, void* addr, size_t len)
Edit
Change a property. This is a DryOS call.
- property: an ID from the List of Properties (they are declared in property.h)
- addr: pointer to the new property value
- len: size of the value located at addr
- What data type do properties have? I believe most of them are integers or strings. The list of properties do not specify the data type.
Example code from lens.h:
static inline void lens_set_aperture(unsigned aperture)
{
prop_request_change( PROP_APERTURE, &aperture, sizeof(aperture) );
}
#define PROP_HANDLER(id)
Edit
Use this to get notified when a property changes. This macro allows you to declare a function which is called automatically (something like interrupts).
- id: an ID from the List of Properties (they are declared in property.h)
Example code from lens.c:
PROP_HANDLER( PROP_ISO )
{
const uint32_t raw = *(uint32_t *) buf;
lens_info.raw_iso = raw;
lens_info.iso = raw/2 < COUNT(iso_values)
? iso_values[ raw / 2 ]
: 0;
return prop_cleanup( token, property );
}
void prop_get_value(unsigned property, void * addr, size_t * len);
Edit
Parameters: same as prop_request_change. This is a DryOS call, only identified in 5D2/1.1.0. Not sure if it works in 550D.
todo: Does initial value of len matter?
lens.c and lens.h
Edit
Control ISO, shutter, aperture and stuff like that.
Semaphores
Edit
lens_sem = create_named_semaphore( "lens_info", 1 ); focus_done_sem = create_named_semaphore( "focus_sem", 1 ); job_sem = create_named_semaphore( "job", 1 );
Functions
Edit
void lens_set_aperture(unsigned aperture)
Edit
- aperture: see lens.h for possible values. There are macros like APERTURE_1_8, APERTURE_4_0 and so on.
void lens_set_iso(unsigned iso)
Edit
- iso: see lens.h for possible values. There are macros from ISO_100 to ISO_12500.
void lens_set_shutter(unsigned shutter)
Edit
- shutter: see lens.h for possible values. There are macros from SHUTTER_30 to SHUTTER_4000.
void lens_set_ae(int cmd)
Edit
Exposure compensation?
- cmd: it seems to be the desired exposure, in EV, or 1/3 EV, or something like this. Not sure.
int lens_get_ae(void)
Edit
// This is currently broken. Returns 0.
int lens_take_picture(int wait)
Edit
Takes a picture.
- wait: number of milliseconds to wait (this is a timeout)
Internally, this function calls:
call( "Release" );
and does a bit of black magic with some semaphores.
uint16_t bswap16(uint16_t val)
Edit
bswap16(0xABCD) => 0xCDAB
Edit
ptp.h and ptp.c
Edit
These files contain macros and functions for extending PTP capabilities of the camera.
Until I understand how this works, see the PTP page.
It would be nice to create some Python wrappers for these capabilities. See Remote_control_with_PTP_and_Python. I'll try to create some Python bindings for Mweerden's patched libptp/ptpcam. Also, I'd like to be able to upload files on the camera via PTP and to poke/peek memory locations. CHDK does this afaik.
tasks.h
Edit
#define INIT_FUNC(NAME, ENTRY)
Edit
Define an initialization function, which is executed at firmware startup (I think so).
- NAME: a string, used in debug messages
- ENTRY: pointer to a function with this signature: static void functionname(void)
These init functions are called here:
- [5d-hack.c] my_init_task -> menu_init -> call_init_funcs
#define TASK_CREATE(NAME, ENTRY, ARG, PRIORITY, FLAGS)
Edit
Creates a task which runs in parallel with the Canon firmware. Each feature in ML seems to have its own task: focus_task, bracket_task, dump_task, zebra_task, menu_task and so on.
- NAME: a string, used in debug messages.
- ENTRY: pointer to a function with this signature: static void functionname(void)
- ARG: it seems unused, and always 0.
- PRIORITY: Task priority. Values from ML code: 0x10, 0x18, 0x1e, 0x1f. I don't know whether higher values mean higher priority or viceversa. [AJ: 0x1F = 31 is the lowest prioriity. Example task priorities http://magiclantern.wikia.com/wiki/2.0.4_Tasks ]
- FLAGS: 0x1000 (I don't know what that means)
The tasks are started in 5d-hack.c, in my_init_task, AFTER call_init_funcs, with several calls to task_create, which is a function from the Canon code.
#define TASK_OVERRIDE(orig_func, replace_func)
Edit
This REPLACES a Canon task with some custom function from Magic Lantern. I don't understand how it does that, but it works!!!
$ grep -nr "TASK_OVERRIDE" ./ ./tasks.h:107:#define TASK_OVERRIDE( orig_func, replace_func ) \ ./hotplug.c:68:TASK_OVERRIDE( hotplug_task, my_hotplug_task ); ./gui.c:221:TASK_OVERRIDE( gui_main_task, my_gui_main_task ); ./audio.c:876:TASK_OVERRIDE( sounddev_task, my_sounddev_task ); ./audio.c:977:TASK_OVERRIDE( audio_level_task, my_audio_level_task );