Script to skip bad ISO valuese when setting ISO values with the Canon dials

Started by chris88, April 17, 2016, 07:50:59 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

chris88

Hello together,
I am totally new to LUA scripting, but my goal is to write a script which is able to skip several ISO values when setting the ISO values via the canon scroll wheel (pressing ISO button + selecting ISO via scroll wheel). I started by trying to alter the copy2m.lua script. config.lua is also present in the script directory. Currently I have this code which does not run yet. I try to dig deeper. But I think currently I'm struggling with the handler concept. I do not know what the handler values can be and how I could find out this. Maybe someone could help me a little bit with this. my preferred way would also be to set the camera.iso.value istead of .raw, but I think the handler maybe in raw format. I don't know.
For the Canon 6D I read out the ISO RAW/VALUE/APEX data, which you could see below. When trying to read out property.ISO and property.ISO_AUTO it only displays "table: p" but I do not know how to look into the values of this table.


--copies the shutter, aperture, and iso of the current mode when switching to M mode
require("config")

--class to keep track of property values using prophandlers
prop_value = {}
prop_value.__index = prop_value

function prop_value.create(...)
    local pv =
    {
        value = 0,
        previous = 0,
        time = dryos.ms_clock,
        props = {...}
    }
    setmetatable(pv,prop_value)
    return pv
end

function prop_value:enable()
    for i,v in ipairs(self.props) do
        function v.handler(prop,value) self:set(value) end
    end
end

function prop_value:disable()
    for i,v in ipairs(self.props) do
        v.handler = nil
    end
end

function prop_value:set(value)
    if value ~= 0 then
        self.previous = self.value
        self.value = value
    end
end

function prop_value:get()
    --ignore value if we've been in the current mode for less than 1 sec
    if dryos.ms_clock - self.time < 1000 then
        return self.previous
    else
        return self.value
    end
end


local iso_value = prop_value.create(property.ISO,property.ISO_AUTO)

--will be set as the prop handler for property.ISO, when enabled
--
--                     RAW     VALUE   APEX
-- ISO Automatic       0       0       -40
-- ISO L               64      50      40
-- ISO 100             72      100     50
-- ISO 125             75      125     53
-- ISO 160             77      160     56
-- ISO 200             80      200     60
-- ISO 250             83      250     63
-- ISO 320             85      320     66
-- ISO 400             88      400     70
-- ISO 500             91      500     73
-- ISO 640             93      640     76
-- ISO 800             96      800     80
-- ISO 1000            99      1000    83
-- ISO 1250            101     1250    86
-- ISO 1600            104     1600    90
-- ISO 2000            107     2000    93
-- ISO 2500            109     2500    96
-- ISO 3200            112     3200    100
-- ISO 4000            115     4000    103
-- ISO 5000            117     5000    106
-- ISO 6400            120     6400    110
-- ISO 8000            123     8000    113
-- ISO 10000           125     10000   116
-- ISO 12800           128     12800   120
-- ISO 16000           131     16000   123
-- ISO 20000           133     20000   126
-- ISO 25600           136     25600   130
-- ISO H1              144     51200   140
-- ISO H2              152     102000  150


function iso_mode_handler(self,value)
    if value ~= 0 then
        local i = iso_value:get()
        if i == 72 then camera.iso.raw = 77 end -- ISO 100 gets ISO 160
        if i == 75 then camera.iso.raw = 77 end -- ISO 125 gets ISO 160
        if i == 80 then camera.iso.raw = 85 end -- ISO 200 gets ISO 320
        if i == 83 then camera.iso.raw = 85 end -- ISO 250 gets ISO 320
        if i == 88 then camera.iso.raw = 93 end -- ISO 400 gets ISO 640
        if i == 91 then camera.iso.raw = 93 end -- ISO 500 gets ISO 640
        if i == 99 then camera.iso.raw = 101 end -- ISO 1000 gets ISO 1250
        if i == 107 then camera.iso.raw = 109 end -- ISO 2000 gets ISO 2500
        if i == 115 then camera.iso.raw = 117 end -- ISO 4000 gets ISO 5000
    else
        iso_value.time = dryos.ms_clock
    end
end


skipbadiso_menu = menu.new
{
    parent = "Expo",
    name = "Bad ISO skipping",
    help = "Skips bad ISO values",
    choices = {"OFF","ON"},
    value = "OFF"
}

function skipbadiso_menu:select(delta)
    if self.value == "OFF" then self.value = "ON" else self.value = "OFF" end
    skipbadiso_update(self.value)
end

--start/stop the prop handlers to enable/disable this script's functionality
function skipbadiso_update(value)
    if value == "ON" then
        iso_value:enable()
        property.ISO.handler = iso_mode_handler
    else
        iso_value:disable()
        property.ISO.handler = nil
    end
end

config.create_from_menu(skipbadiso_menu)
skipbadiso_update(skipbadiso_menu.value)



The idea behind:

When ISO is set to auto or any value not mentioned in the code above the camera will stay at this ISO value. But if the ISO is set to 100,125,200,250,400,500,1000,2000 or 4000 it will switch to another ISO value by it's own.

chris88

Ok, this one works at least in the forward direction:

--copies the shutter, aperture, and iso of the current mode when switching to M mode
require("config")

--will be set as the prop handler for property.ISO, when enabled
--
--                     RAW     VALUE   APEX
-- ISO Automatic       0       0       -40
-- ISO L               64      50      40
-- ISO 100             72      100     50
-- ISO 125             75      125     53
-- ISO 160             77      160     56
-- ISO 200             80      200     60
-- ISO 250             83      250     63
-- ISO 320             85      320     66
-- ISO 400             88      400     70
-- ISO 500             91      500     73
-- ISO 640             93      640     76
-- ISO 800             96      800     80
-- ISO 1000            99      1000    83
-- ISO 1250            101     1250    86
-- ISO 1600            104     1600    90
-- ISO 2000            107     2000    93
-- ISO 2500            109     2500    96
-- ISO 3200            112     3200    100
-- ISO 4000            115     4000    103
-- ISO 5000            117     5000    106
-- ISO 6400            120     6400    110
-- ISO 8000            123     8000    113
-- ISO 10000           125     10000   116
-- ISO 12800           128     12800   120
-- ISO 16000           131     16000   123
-- ISO 20000           133     20000   126
-- ISO 25600           136     25600   130
-- ISO H1              144     51200   140
-- ISO H2              152     102000  150


function iso_mode_handler(self,value)
    if value ~= 0 then
        if value == 72 then camera.iso.raw = 77 end -- ISO 100 gets ISO 160
        if value == 75 then camera.iso.raw = 77 end -- ISO 125 gets ISO 160
        if value == 80 then camera.iso.raw = 85 end -- ISO 200 gets ISO 320
        if value== 83 then camera.iso.raw = 85 end -- ISO 250 gets ISO 320
        if value == 88 then camera.iso.raw = 93 end -- ISO 400 gets ISO 640
        if value == 91 then camera.iso.raw = 93 end -- ISO 500 gets ISO 640
        if value == 99 then camera.iso.raw = 101 end -- ISO 1000 gets ISO 1250
        if value == 107 then camera.iso.raw = 109 end -- ISO 2000 gets ISO 2500
        if value == 115 then camera.iso.raw = 117 end -- ISO 4000 gets ISO 5000
    end
end

skipbadiso_menu = menu.new
{
    parent = "Expo",
    name = "Bad ISO skipping",
    help = "Skips bad ISO values",
    choices = {"OFF","ON"},
    value = "OFF"
}

function skipbadiso_menu:select(delta)
    if self.value == "OFF" then self.value = "ON" else self.value = "OFF" end
    skipbadiso_update(self.value)
end

--start/stop the prop handlers to enable/disable this script's functionality
function skipbadiso_update(value)
    if value == "ON" then
        property.ISO.handler = iso_mode_handler
    else
        property.ISO.handler = nil
    end
end

config.create_from_menu(skipbadiso_menu)
skipbadiso_update(skipbadiso_menu.value)


Now I have to save the previous values to be able to reduce the ISO levels again, once I increased them. Any ideas?

chris88

Ok, this script now seems to work fine:

-- This script allows to skip bad ISO values when selecting ISO via the Canon menu or dials
require("config")

local old_value = 0
local new_value = 0

--will be set as the prop handler for property.ISO, when enabled
--
--                     RAW     VALUE   APEX
-- ISO Automatic       0       0       -40
-- ISO L               64      50      40
-- ISO 100             72      100     50
-- ISO 125             75      125     53
-- ISO 160             77      160     56
-- ISO 200             80      200     60
-- ISO 250             83      250     63
-- ISO 320             85      320     66
-- ISO 400             88      400     70
-- ISO 500             91      500     73
-- ISO 640             93      640     76
-- ISO 800             96      800     80
-- ISO 1000            99      1000    83
-- ISO 1250            101     1250    86
-- ISO 1600            104     1600    90
-- ISO 2000            107     2000    93
-- ISO 2500            109     2500    96
-- ISO 3200            112     3200    100
-- ISO 4000            115     4000    103
-- ISO 5000            117     5000    106
-- ISO 6400            120     6400    110
-- ISO 8000            123     8000    113
-- ISO 10000           125     10000   116
-- ISO 12800           128     12800   120
-- ISO 16000           131     16000   123
-- ISO 20000           133     20000   126
-- ISO 25600           136     25600   130
-- ISO H1              144     51200   140
-- ISO H2              152     102000  150

function iso_mode_handler(self,value)
    old_value = new_value
    new_value = value
   
    -- Skipped ISO values when ISO is increasing
    if (value == 72  and old_value < 72) then camera.iso.raw = 77 end -- ISO 100 gets ISO 160
    if (value == 75  and old_value < 75) then camera.iso.raw = 77 end -- ISO 125 gets ISO 160
    if (value == 80  and old_value < 80) then camera.iso.raw = 85 end -- ISO 200 gets ISO 320
    if (value == 83  and old_value < 83) then camera.iso.raw = 85 end -- ISO 250 gets ISO 320
    if (value == 88  and old_value < 88) then camera.iso.raw = 93 end -- ISO 400 gets ISO 640
    if (value == 91  and old_value < 91) then camera.iso.raw = 93 end -- ISO 500 gets ISO 640
    if (value == 99  and old_value < 99) then camera.iso.raw = 101 end -- ISO 1000 gets ISO 1250
    if (value == 107 and old_value < 107) then camera.iso.raw = 109 end -- ISO 2000 gets ISO 2500
    if (value == 115 and old_value < 115) then camera.iso.raw = 117 end -- ISO 4000 gets ISO 5000

    -- Skipped ISO values when ISO is decreasing
    if (value == 72  and old_value > 72) then camera.iso.raw = 0 end -- ISO 100 gets ISO AUTO
    if (value == 75  and old_value > 75) then camera.iso.raw = 0 end -- ISO 125 gets ISO AUTO
    if (value == 80  and old_value > 80) then camera.iso.raw = 77 end -- ISO 200 gets ISO 160
    if (value == 83  and old_value > 83) then camera.iso.raw = 77 end -- ISO 250 gets ISO 160
    if (value == 88  and old_value > 88) then camera.iso.raw = 85 end -- ISO 400 gets ISO 320
    if (value == 91  and old_value > 91) then camera.iso.raw = 85 end -- ISO 500 gets ISO 320
    if (value == 99  and old_value > 99) then camera.iso.raw = 96 end -- ISO 1000 gets ISO 800
    if (value == 107 and old_value > 107) then camera.iso.raw = 104 end -- ISO 2000 gets ISO 1600
    if (value == 115 and old_value > 115) then camera.iso.raw = 112 end -- ISO 4000 gets ISO 3200
   
end


skipbadiso_menu = menu.new
{
    parent = "Expo",
    name = "Bad ISO skipping",
    help = "Skips bad ISO values",
    choices = {"OFF","ON"},
    value = "OFF"
}


function skipbadiso_menu:select(delta)
    if self.value == "OFF" then self.value = "ON" else self.value = "OFF" end
    skipbadiso_update(self.value)
end

--start/stop the prop handlers to enable/disable this script's functionality
function skipbadiso_update(value)
    if value == "ON" then
        property.ISO.handler = iso_mode_handler
    else
        property.ISO.handler = nil
    end
end

config.create_from_menu(skipbadiso_menu)
skipbadiso_update(skipbadiso_menu.value)


Currently I have only one problem:
When I am decreasing the ISO values I can not switch from ISO125 or ISO100 to ISO50. This does not work:


if (value == 72  and old_value > 72) then camera.iso.raw = 64 end -- ISO 100 gets ISO 50
if (value == 75  and old_value > 75) then camera.iso.raw = 64 end -- ISO 125 gets ISO 50


It always jumps to ISO 100. So I currently decided that I will switch into AUTO ISO instead. This works fine. Does someone have an idea why I can not jump into ISO50 mode?

Frank7D

Maybe something to do with ISO 50 being an "extended" feature?
Also, it is not available with video, if that matters.

chris88

Hm, yes this may be possible. As I do not use video mode at all I do not have any experience there.
Currently, if I want to use ISO50 (never used it, but who knows) I first have to switch to ISO AUTO and then up to 50 as the switching levels are:

AUTO > L(50) > 160 > 320 > ...
... > 320 > 160 > AUTO


And here is the final version - tested on a Canon 6D 1.1.6. For a better robustness I changed the initialization of the local variables:

-- This script allows to skip bad ISO values when selecting ISO via the Canon menu or dials

require("config")

local old_value = camera.iso.raw
local new_value = camera.iso.raw

-- ISO values for RAW/VALUE/APEX (Canon 6D 1.1.6)
--
--                     RAW     VALUE   APEX
-- ISO Automatic       0       0       -40
-- ISO L               64      50      40
-- ISO 100             72      100     50
-- ISO 125             75      125     53
-- ISO 160             77      160     56
-- ISO 200             80      200     60
-- ISO 250             83      250     63
-- ISO 320             85      320     66
-- ISO 400             88      400     70
-- ISO 500             91      500     73
-- ISO 640             93      640     76
-- ISO 800             96      800     80
-- ISO 1000            99      1000    83
-- ISO 1250            101     1250    86
-- ISO 1600            104     1600    90
-- ISO 2000            107     2000    93
-- ISO 2500            109     2500    96
-- ISO 3200            112     3200    100
-- ISO 4000            115     4000    103
-- ISO 5000            117     5000    106
-- ISO 6400            120     6400    110
-- ISO 8000            123     8000    113
-- ISO 10000           125     10000   116
-- ISO 12800           128     12800   120
-- ISO 16000           131     16000   123
-- ISO 20000           133     20000   126
-- ISO 25600           136     25600   130
-- ISO H1              144     51200   140
-- ISO H2              152     102000  150

--will be set as the prop handler for property.ISO, when enabled
function iso_mode_handler(self,value)
    old_value = new_value
    new_value = value
   
    -- Skipped ISO values when ISO is increasing
    if (value == 72  and old_value < 72)  then camera.iso.raw = 77  end -- ISO 100  gets ISO 160
    if (value == 75  and old_value < 75)  then camera.iso.raw = 77  end -- ISO 125  gets ISO 160
    if (value == 80  and old_value < 80)  then camera.iso.raw = 85  end -- ISO 200  gets ISO 320
    if (value == 83  and old_value < 83)  then camera.iso.raw = 85  end -- ISO 250  gets ISO 320
    if (value == 88  and old_value < 88)  then camera.iso.raw = 93  end -- ISO 400  gets ISO 640
    if (value == 91  and old_value < 91)  then camera.iso.raw = 93  end -- ISO 500  gets ISO 640
    if (value == 99  and old_value < 99)  then camera.iso.raw = 101 end -- ISO 1000 gets ISO 1250
    if (value == 107 and old_value < 107) then camera.iso.raw = 109 end -- ISO 2000 gets ISO 2500
    if (value == 115 and old_value < 115) then camera.iso.raw = 117 end -- ISO 4000 gets ISO 5000

    -- Skipped ISO values when ISO is decreasing
    if (value == 72  and old_value > 72)  then camera.iso.raw = 0   end -- ISO 100  gets ISO AUTO
    if (value == 75  and old_value > 75)  then camera.iso.raw = 0   end -- ISO 125  gets ISO AUTO
    if (value == 80  and old_value > 80)  then camera.iso.raw = 77  end -- ISO 200  gets ISO 160
    if (value == 83  and old_value > 83)  then camera.iso.raw = 77  end -- ISO 250  gets ISO 160
    if (value == 88  and old_value > 88)  then camera.iso.raw = 85  end -- ISO 400  gets ISO 320
    if (value == 91  and old_value > 91)  then camera.iso.raw = 85  end -- ISO 500  gets ISO 320
    if (value == 99  and old_value > 99)  then camera.iso.raw = 96  end -- ISO 1000 gets ISO 800
    if (value == 107 and old_value > 107) then camera.iso.raw = 104 end -- ISO 2000 gets ISO 1600
    if (value == 115 and old_value > 115) then camera.iso.raw = 112 end -- ISO 4000 gets ISO 3200 
end

skipbadiso_menu = menu.new
{
    parent = "Expo",
    name = "Bad ISO skipping",
    help = "Skips bad ISO values",
    choices = {"OFF","ON"},
    value = "OFF"
}

function skipbadiso_menu:select(delta)
    if self.value == "OFF" then self.value = "ON" else self.value = "OFF" end
    skipbadiso_update(self.value)
end

--start/stop the prop handlers to enable/disable this script's functionality
function skipbadiso_update(value)
    if value == "ON" then
        property.ISO.handler = iso_mode_handler
    else
        property.ISO.handler = nil
    end
end

config.create_from_menu(skipbadiso_menu)
skipbadiso_update(skipbadiso_menu.value)





And by the way, sorry, I think this section of the forum is only for PicoC scripts. So if someone would be so kind and could move this thread in a LUA section? Thanks

dmilligan

PicoC is gone, so really this section of the forum should become the Lua scripting area.

Just a little hint: you can compact your code quite a bit if you create a table of ISOs to skip and iterate it in a loop, rather than having a whole a bunch of if statements.


isos_to_skip = {100,200,400,800}


I would also suggest reading:
http://www.magiclantern.fm/forum/index.php?topic=9867
http://www.magiclantern.fm/forum/index.php?topic=10111.0

chris88

Hi dmilligan
thank you for your tip regarding the many if statements. You are right, your approach would be much cleaner. As I am totally new to coding I have some questions:

I coded (but not tested) this:

-- This script allows to skip bad ISO values when selecting ISO via the Canon menu or dials

require("config")

-- ISO values for RAW/VALUE/APEX (Canon 6D 1.1.6)
--
--                     RAW     VALUE   APEX
-- ISO Automatic       0       0       -40
-- ISO L               64      50      40
-- ISO 100             72      100     50
-- ISO 125             75      125     53
-- ISO 160             77      160     56
-- ISO 200             80      200     60
-- ISO 250             83      250     63
-- ISO 320             85      320     66
-- ISO 400             88      400     70
-- ISO 500             91      500     73
-- ISO 640             93      640     76
-- ISO 800             96      800     80
-- ISO 1000            99      1000    83
-- ISO 1250            101     1250    86
-- ISO 1600            104     1600    90
-- ISO 2000            107     2000    93
-- ISO 2500            109     2500    96
-- ISO 3200            112     3200    100
-- ISO 4000            115     4000    103
-- ISO 5000            117     5000    106
-- ISO 6400            120     6400    110
-- ISO 8000            123     8000    113
-- ISO 10000           125     10000   116
-- ISO 12800           128     12800   120
-- ISO 16000           131     16000   123
-- ISO 20000           133     20000   126
-- ISO 25600           136     25600   130
-- ISO H1              144     51200   140
-- ISO H2              152     102000  150

--will be set as the prop handler for property.ISO, when enabled

local old_value = camera.iso.raw
local new_value = camera.iso.raw
local ISO_step_up={77,77,85,85,93,93,101,109,117}   -- ISO values skipped to when increasing ISO
local ISO_to_skip={72,75,80,83,88,91,99, 107,115}   -- ISO values to skip
local ISO_step_dn={77,77,77,77,85,85,96, 104,112}   -- ISO values skipped to when decreasing ISO
local table_length=#ISO_to_skip
local i=1

function iso_mode_handler(self,value)
    old_value = new_value
    new_value = value

    for i = 1, table_length, 1 do
        if new_value == ISO_to_skip[i] then
            if old_value < new_value then camera.iso.raw = ISO_step_up[i] end -- ISO increasing
            if old_value > new_value then camera.iso.raw = ISO_step_dn[i] end  -- ISO decreasing
            break -- exit "for" statement
        end
    end

end

skipbadiso_menu = menu.new
{
    parent = "Expo",
    name = "Bad ISO skipping",
    help = "Skips bad ISO values",
    choices = {"OFF","ON"},
    value = "OFF"
}

function skipbadiso_menu:select(delta)
    if self.value == "OFF" then self.value = "ON" else self.value = "OFF" end
    skipbadiso_update(self.value)
end

--start/stop the prop handlers to enable/disable this script's functionality
function skipbadiso_update(value)
    if value == "ON" then
        property.ISO.handler = iso_mode_handler
    else
        property.ISO.handler = nil
    end
end

config.create_from_menu(skipbadiso_menu)
skipbadiso_update(skipbadiso_menu.value)


1 Would this work this way ?
2 Can I definde my local variables (including the tables) in this way ?
3 Can I use "break" like I used it, or do I have to use "do break end" instead to skip the rest of the for statement ?
4 Can I access table values by using table_var_name ?
5 Can I get the table length by using #table_var_name ?
6 Do I use the for statement correctly ?
7 Do I need to initialize also the counter i as local via "local i" ?
8 Is there some way to test lua scripts on the PC ?


Here is only the relevant part the questions are for:


local old_value = camera.iso.raw
local new_value = camera.iso.raw
local ISO_step_up={77,77,85,85,93,93,101,109,117}   -- ISO values skipped to when increasing ISO
local ISO_to_skip={72,75,80,83,88,91,99, 107,115}   -- ISO values to skip
local ISO_step_dn={77,77,77,77,85,85,96, 104,112}   -- ISO values skipped to when decreasing ISO
local table_length=#ISO_to_skip
local i=1

function iso_mode_handler(self,value)
    old_value = new_value
    new_value = value

    for i = 1, table_length, 1 do
        if new_value == ISO_to_skip[i] then
            if old_value < new_value then camera.iso.raw = ISO_step_up[i] end -- ISO increasing
            if old_value > new_value then camera.iso.raw = ISO_step_dn[i] end  -- ISO decreasing
            break -- exit "for" statement
        end
    end

end



Many thanks in advance,
Chris



dmilligan

It looks correct to me (didn't try it).

You can actually do a little trick to make the for loop even simpler:


for i,v in ipairs(ISO_to_skip) do
        if new_value == v then
            if old_value < new_value then camera.iso.raw = ISO_step_up[i] end -- ISO increasing
            if old_value > new_value then camera.iso.raw = ISO_step_dn[i] end  -- ISO decreasing
            break -- exit "for" statement
        end
end


The answers to most of your questions can be found here: http://www.lua.org/manual/5.3/manual.html

8. You can check if the script's syntax is valid using luac on your computer, but actually running it with the plain lua interpreter on the computer will fail (the ML APIs will be missing). You can try running it under QEMU, but getting that setup and working is quite a challenge.

chris88

Hey dmilligan,
thanks a lot for your tip. I optimized the script now. It is working perfectly:

-- Bad ISO Skipper
-- This script allows to skip certain ISO values when selecting ISO via the Canon menu or dials
-- Developed and tested for Canon 6D 1.1.6

require("config")

-- ISO values for RAW/VALUE/APEX (Canon 6D 1.1.6)
--
--                     RAW     VALUE   APEX
-- ISO Automatic       0       0       -40
-- ISO L               64      50      40
-- ISO 100             72      100     50
-- ISO 125             75      125     53
-- ISO 160             77      160     56
-- ISO 200             80      200     60
-- ISO 250             83      250     63
-- ISO 320             85      320     66
-- ISO 400             88      400     70
-- ISO 500             91      500     73
-- ISO 640             93      640     76
-- ISO 800             96      800     80
-- ISO 1000            99      1000    83
-- ISO 1250            101     1250    86
-- ISO 1600            104     1600    90
-- ISO 2000            107     2000    93
-- ISO 2500            109     2500    96
-- ISO 3200            112     3200    100
-- ISO 4000            115     4000    103
-- ISO 5000            117     5000    106
-- ISO 6400            120     6400    110
-- ISO 8000            123     8000    113
-- ISO 10000           125     10000   116
-- ISO 12800           128     12800   120
-- ISO 16000           131     16000   123
-- ISO 20000           133     20000   126
-- ISO 25600           136     25600   130
-- ISO H1              144     51200   140
-- ISO H2              152     102000  150

--will be set as the prop handler for property.ISO, when enabled

local old_value = camera.iso.raw
local new_value = camera.iso.raw
local ISO_step_up={}
local ISO_to_skip={}
local ISO_step_dn={}

function iso_mode_handler(self,value)
    for i,v in ipairs(ISO_to_skip) do
       if (value == old_value) then
          break
       elseif (value == v and value > old_value) then
          camera.iso.raw = ISO_step_up[i]
          break
       elseif (value == v and value < old_value) then
          camera.iso.raw = ISO_step_dn[i]
          break
       end
    end
    old_value = value
end

skipbadiso_menu = menu.new
{
    parent = "Expo",
    name = "Bad ISO skipping",
    help = "Skips bad ISO values",
    choices = {"OFF","ON","Only 160s"},
    value = "OFF"
}

function skipbadiso_menu:select(delta)
    if     self.value == "OFF" then self.value = "ON"
    elseif self.value == "ON"  then self.value = "Only 160s"
    else   self.value = "OFF" end
    skipbadiso_update(self.value)
end

--start/stop the prop handlers to enable/disable this script's functionality
function skipbadiso_update(value)
    if value == "ON" then
        ISO_step_up={77,77,85,85,93,93,101,109,117}   -- ISO values skipped to when increasing ISO
        ISO_to_skip={72,75,80,83,88,91,99,107,115}   -- ISO values to skip
        ISO_step_dn={77,77,77,77,85,85,96,104,112}   -- ISO values skipped to when decreasing ISO
        property.ISO.handler = iso_mode_handler
    elseif value == "Only 160s" then
        ISO_step_up={77,77,85,85,93,93,101,101,109,109,117,117,125,125,125}
        ISO_to_skip={72,75,80,83,88,91,96,99,104,107,112,115,120,123,128}
        ISO_step_dn={77,77,77,77,85,85,93,93,101,101,109,109,117,117,125}
        property.ISO.handler = iso_mode_handler
    else
        property.ISO.handler = nil
    end
end

config.create_from_menu(skipbadiso_menu)
skipbadiso_update(skipbadiso_menu.value)


The only thing which I am struggling with is the menu. I tryed it but so far I have no clue how this is working. By using my approach it is not relevant what arrow key is pressed on the camera, the menu selection every time selects the next value like in a circle. This is working fine, but it would be much nicer if I could use the arrow key to directly select the entry.

A little example:

   Off
> On
   Only 160s

If I want to select Off I have to press a key twice, because currently the state machine is: Off > On > Only 160s > Off > On > ... and so on.
It would be much nicer if I could use the arrow up key to directly select "Off". But I do not know how to implement this. Does this have to be a Submenu? Or could I also get it to work without a submenu?

chris88

Here the relevant menu code. Any ideas how I could make the menu the way I described it above?

skipbadiso_menu = menu.new
{
    parent = "Expo",
    name = "Bad ISO skipping",
    help = "Skips bad ISO values",
    choices = {"OFF","ON","Only 160s"},
    value = "OFF"
}

function skipbadiso_menu:select(delta)
    if     self.value == "OFF" then self.value = "ON"
    elseif self.value == "ON"  then self.value = "Only 160s"
    else   self.value = "OFF" end
    skipbadiso_update(self.value)
end

function skipbadiso_update(value)
    if value == "ON" then
        print ("ON")
    elseif value == "Only 160s" then
        print ("Only 160s")
    else
        print ("OFF")
    end
end

skipbadiso_update(skipbadiso_menu.value)