https://bitbucket.org/hudson/magic-lantern
Raw File
Tip revision: 99c7e675fe97cda7a637b30391efe9d774e91278 authored by a1ex on 01 April 2015, 12:57:31 UTC
tiny8086: renamed original README
Tip revision: 99c7e67
lightsensor.c
/** \file
 * LCD RemoteShot for 5D (with ambient light se)
 * 
 * (C) 2012 Alex Dumitrache, broscutamaker@gmail.com
 */
/*
 * Magic Lantern is Copyright (C) 2009 Trammell Hudson <hudson+ml@osresearch.net>
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#include "dryos.h"
#include "bmp.h"
#include "version.h"
#include "config.h"
#include "menu.h"
#include "property.h"
#include "lens.h"
#include "gui.h"


int lcd_sensor_shortcuts = 0;
int get_lcd_sensor_shortcuts() { return lcd_sensor_shortcuts; }

CONFIG_INT( "lcd.release", lcd_release_running, 0);

void display_lcd_remote_icon(int x0, int y0);

void 
lcd_release_display( void * priv, int x, int y, int selected )
{
    int v = (*(int*)priv);
    bmp_printf(
        selected ? MENU_FONT_SEL : MENU_FONT,
        x, y,
        "LCDsensor Remote: %s",
        v == 1 ? "Near" : v == 2 ? (get_mlu() ? "Away/MLU" : "Away") : v == 3 ? "Wave" : "OFF"
    );
    if (v) display_lcd_remote_icon(x-25, y+5);
    menu_draw_icon(x, y, v ? MNI_NONE : MNI_OFF, 0);
}

extern int remote_shot_flag; // from shoot.c
int wave_count = 0;
int wave_count_countdown = 0;
int lcd_ff_dir = 1;
void sensor_status_trigger(int on)
{
    lens_display_set_dirty();
    if (lcd_release_running && on) info_led_on();

    static int prev = 0;
    int off = !on;
    if (on == prev) // false alarm
        goto end;
    prev = on;

    if (lcd_release_running && off) info_led_off();
    
    if (remote_shot_flag) goto end;

    if (lv && lens_info.job_state == 0 && lcd_release_running == 0 && is_follow_focus_active() && get_follow_focus_mode()==1) // FF on LCD sensor
    {
        if (on)
        {
            lens_focus_start( lcd_ff_dir * get_follow_focus_dir_h() );
        }
        else
        {
            lens_focus_stop();
            lcd_ff_dir = -lcd_ff_dir;
        }
    }
    else
    if (lcd_release_running && gui_state == GUISTATE_IDLE && !is_intervalometer_running())
    {
        if (gui_menu_shown()) goto end;
        if (lcd_release_running == 1 && off) goto end;
        if (lcd_release_running == 2 && on )
        {
            if (get_mlu()) schedule_mlu_lock();
            goto end;
        }
        if (lcd_release_running == 3) { wave_count++; wave_count_countdown = 50; }
        if (lcd_release_running == 3 && wave_count < 5) goto end;

        if (lcd_release_running == 3 && RECORDING) schedule_movie_end(); // wave mode is allowed to stop movies
        else if (RECORDING && is_rack_focus_enabled())
        {
            rack_focus_start_now(0);
        }
        else
        {
            schedule_remote_shot();
        }
        wave_count = 0;
    }
    else wave_count = 0;

    //~ idle_wakeup_reset_counters(-20);

    end:
    return;
}

void lcd_release_step() // to be called from shoot_task
{
    if (wave_count_countdown)
    {
        wave_count_countdown--;
        if (!wave_count_countdown) wave_count = 0;
    }
}

void display_lcd_remote_icon(int x0, int y0)
{
    int cl_on = COLOR_RED;
    int cl_off = lv ? COLOR_WHITE : COLOR_FG_NONLV;
    int cl = display_sensor ? cl_on : cl_off;
    // int bg = lv ? 0 : bmp_getpixel(x0 - 20, 1);

    if (gui_menu_shown()) cl = COLOR_WHITE;

    if (lcd_release_running == 1)
    {
        draw_circle(x0, 10+y0, 8, cl);
        draw_circle(x0, 10+y0, 7, cl);
        draw_line(x0-5,10-5+y0,x0+5,10+5+y0,cl);
        draw_line(x0-5,10+5+y0,x0+5,10-5+y0,cl);
    }
    else if (lcd_release_running == 2)
    {
        draw_circle(x0, 10+y0, 8, cl);
        draw_circle(x0, 10+y0, 7, cl);
        draw_circle(x0, 10+y0, 1, cl);
        draw_circle(x0, 10+y0, 2, cl);
    }
    else if (lcd_release_running == 3)
    {
        int yup = y0;
        int ydn = 10+y0;
        int step = 5;
        int k;
        for (k = 0; k < 2; k++)
        {
            draw_line(x0 - 2*step, ydn, x0 - 1*step, yup, wave_count > 0 ? cl_on : cl_off);
            draw_line(x0 - 1*step, yup, x0 - 0*step, ydn, wave_count > 1 ? cl_on : cl_off);
            draw_line(x0 - 0*step, ydn, x0 + 1*step, yup, wave_count > 2 ? cl_on : cl_off);
            draw_line(x0 + 1*step, yup, x0 + 2*step, ydn, wave_count > 3 ? cl_on : cl_off);
            draw_line(x0 + 2*step, ydn, x0 + 3*step, yup, wave_count > 4 ? cl_on : cl_off);
            x0++;
        }
    }
    else if (lcd_release_running == 0 && is_follow_focus_active() && get_follow_focus_mode()==1 && lv)
    {
        bmp_printf(FONT_MED, x0-10, y0, "FF%s", get_follow_focus_dir_h() * lcd_ff_dir > 0 ? "-" : "+");
        bmp_printf(FONT_LARGE, 650, 50, "FF%s", get_follow_focus_dir_h() * lcd_ff_dir > 0 ? "-" : "+");
    }
    
    //~ if (gui_menu_shown()) return;
    
    //~ static unsigned int prev_lr = 0;
    //~ if (prev_lr != lcd_release_running) bmp_fill(bg, x0 - 20, y0, 40, 20);
    //~ prev_lr = lcd_release_running;
}

int lightsensor_raw_value = 0;
//~ int lightsensor_value = 0;

//~ int is_lightsensor_triggered() { return lightsensor_triggered; }

void LightMeasureCBR(int priv, int light)
{
    lightsensor_raw_value = light;
    //~ bmp_printf(FONT_LARGE, 0, 0, "%d ", light);
}

void light_sensor_task(void* unused)
{
    TASK_LOOP
    {
        // only poll the light sensor when needed (seems to be a bit CPU-intensive)
        int sensor_needed = lcd_release_running || (is_follow_focus_active() && get_follow_focus_mode()==1) || is_menu_active("Debug");
        if (!sensor_needed) { msleep(500); continue; }
        
        msleep(50);
        LightMeasure_n_Callback_r0(LightMeasureCBR, 0);

        int ev_x100 = gain_to_ev_scaled(lightsensor_raw_value, 100);

        static int ev_avg_x100 = 0;
        if (ev_avg_x100 == 0) ev_avg_x100 = ev_x100;
        ev_avg_x100 = (ev_avg_x100 * 63 + ev_x100) / 64;

        static int avg_prev0 = 1000;
        static int avg_prev1 = 1000;
        static int avg_prev2 = 1000;
        static int avg_prev3 = 1000;

        int lightsensor_delta_from_average = ev_x100 - avg_prev3;

        avg_prev3 = avg_prev2;
        avg_prev2 = avg_prev1;
        avg_prev1 = avg_prev0;
        avg_prev0 = ev_avg_x100;

        // trigger at -2 EV under average
        // maintain until -1 EV
        if (lightsensor_delta_from_average < -200) display_sensor = 1;
        else if (lightsensor_delta_from_average > -100) display_sensor = 0;
        
        if (k < 50) k++; // ignore the first cycles: wait for the signal to become stable
        else sensor_status_trigger(display_sensor);
    }
}

TASK_CREATE( "light_sensor_task", light_sensor_task, 0, 0x1c, 0x1000 );
back to top