REMOTE shoot_SticK(Tv, Av, Sv) M-MODE FUNCTION THAT IMPLEMENTS PTM EVENTS
DESCRIPTION
In CHDKPTP the remote shoot -tv= -av= -sv= function causes the liveview to fall back to ISO 100 if user-set via the Canon SET menu to any value other than ISO 100. This has the effect of darkening liveview after a shoot, if for example, liveview is at ISO1600. This implementation solves the problem by getting the current ISO value, shooting and resetting the ISO to restore the original liveview brightness. This code also auto-detects the camera then vectoring out the correct PTM Get and Set addresses, and executes file transfer from the camera to PC after shoot using dcimdl(). I designed the logic so that the camera model is probed only once, ie on the first call to shoot_SticK(). At present, it handles all three known firmware versions of the S90. Please note that this code is not exclusive to the hacked S90 with its CCD hanging out: if you have a remote application with any camera where you want liveview stable in M mode, it will work so long as you find the Get and Set address pointers for your camera.
ADDING A NEW EVENT
First obtain the PTM Get and Set addresses for call_func_ptr() for your camera if it is not in the cam_funcs table already (might be tricky). Add your new event ID (ISO is already coded-in). The code has know which camera_fwversion you have: from the CHDKPTP command line, say !ShowModel() and use that to make a new entry in cam_table. Change my PC_destdir to yours. Detailed instructions are given in the code.
--[[ *** shoot_SticK(Tv, Av, Sv) ***
Mechanism to shoot an S90 in M mode via shoot_SticK(Tv, Av, Sv) call.
Copyright (c) 2013 SticK
License: free and unrestricted use.
Current implementation is for resetting liveview ISO (brightness) to
the value prior to shoot using PTM events.
Steps: 1) For a camera not in the table, from the CHDKPTP command line
say !ShowModel() and note your camera model_version. Ignore
any warning message.
2) Using model_version, create a new entry in the cam_funcs table
and define the PTM_Get and PTM_Set addresses for the event.
3) Add a new PTM event ID eg: local CamPTM_ISO_ID = "0x8006"
]]
local PC_destdir = "G:\\CANON_S90\\" -- Give your PC destination folder for camera image files here -- DO NOT use spaces .. it will truncate.
-- Add a new CamPTM_XXX_ID here (step 3)
local CamPTM_ISO_ID = "0x8006"
local cam_funcs =
{
-- Add an entry here with the PTM Get and Set pointers for your camera. (step 2)
s90_100c =
{
PTM_Get = '0xff8950cc',
PTM_Set = '0xff993e2c',
},
s90_101a =
{
PTM_Get = '0xff8950f8',
PTM_Set = '0xff993e80',
},
s90_101c =
{
PTM_Get = '0xff895148',
PTM_Set = '0xff99403c',
}
}
local current_cam = nil
local function PTM_Get(event_id) -- a return value of -1 indicates Get failure
local l,r = con:execwait(string.format('return call_func_ptr(%s, %s)', current_cam.PTM_Get, event_id))
if l == nil then
warnf('PTM_Get failed %s\n',tostring(r))
return -1
end
return r
end
local function PTM_Set(event_id, to_value) -- Returns true if Set successful, false if not.
local l,r = con:execwait(string.format('return call_func_ptr(%s, %s, %d)', current_cam.PTM_Set, event_id, to_value))
if l == nil then
warnf('PTM_Set failed %s\n',tostring(r))
return false
end
return true
end
local function set_CameraModel(do_show) --sets the camera Canon FW version (100c, 101a etc) for vectoring call_func_ptr() calls.
local l,bi = con:execwait('return get_buildinfo()')
if l == nil then
warnf('set_CameraModel(): get_buildinfo() failed: %s. Some operations will fail.\n', tostring(bi))
current_cam = nil
return false
end
local cam = bi.platform .. '_' .. bi.platsub
if do_show == true then
printf('Camera: %s\n', cam) -- use this result to define a new table entry for your camera. (step 1)
end
current_cam = cam_funcs[cam] -- will be nil if not known in table
if current_cam == nil then
warnf('Failed to set camera model %s (not found in table). Some operations will fail.\n', cam)
return false
end
return true
end
function ShowModel() -- (step 1)
set_CameraModel(true)
end
-- ==============================================================================
local function dcimdl(destdir,del,pretend) -- transfers image files from SD card to PC and erases them from SD card.
if pretend then
pretend = '-pretend '
else
pretend = ''
end
local dcim,err=con:listdir('A/DCIM')
if not dcim then
printf('error listing directory %s\n',tostring(err))
return
end
for i,dname in ipairs(dcim) do
if dname ~= 'CANONMSC' then
cli:print_status(cli:execute('mdl '..pretend..' -fmatch=%.[JDC][PNR][G2W]$ DCIM/'..dname..' '..destdir))
end
end
if del then
cli:print_status(cli:execute('rm '..pretend..' -skip_topdirs DCIM'))
end
end
local function local_shoot(tv, av, canon_sv, destdir) -- usage: >!local_shoot(1/8, 2.8, 400, "C:\\CANON_S90\\")
local sv = canon_sv / 1.6461 -- ISO correction for S90 so that CHDK EXIF data is the same as Canon.
cli:print_status(cli:execute('shoot -tv='..tv..' -av='..av..' -sv='..sv..''))
sys.sleep(2400)
local l,r=con:execwait('return get_meminfo().free_size')
print(" free", r) -- in DOS cmd box
printf(" free: %s\n",r) -- in CHDKPTP log window
dcimdl(destdir, true, false)
end
function shoot_SticK(Tv, Av, Sv)
if current_cam == nil then
if (set_CameraModel(false) == false) then
warnf("WARNING: shoot_SticK(): call request not executed: function pointer addresses missing.\n");
return
end
end
local r = PTM_Get(CamPTM_ISO_ID) -- save the current ISO index for liveview
if r == -1 then
warnf("shoot_SticK(): call request not executed: function pointer addresses missing.\n");
return
end
-- printf("Current ISO index setting=%s\n", r)
local_shoot(Tv, Av, Sv, PC_destdir)
sys.sleep(20)
local l = PTM_Set(CamPTM_ISO_ID, r) -- restore the current ISO index for liveview
if l == false then
warnf("shoot_SticK(): unable to set PTM: camera state may be indeterminate.\n");
return
end
sys.sleep(20)
con:execwait('press("shoot_half")') -- update liveview brightness
con:execwait('release("shoot_half")')
end
Usage: CHDKPTP command line example:
!shoot_SticK(1/8,5.6,200)