Mode dial overriding - General Discussion and Assistance - CHDK Forum

Mode dial overriding

  • 4 Replies
  • 2217 Views
Mode dial overriding
« on: 02 / September / 2011, 05:12:59 »
Advertisements
Hey all, I've got this working so figured I'd share it.  I wanted a solution that works outside scripting and there's currently nothing in place that reads the dial. I know there was an effort a while back to do this, but it never got integrated into the trunk and that ones based on a old version of CHDK.

I don't know if it's just my camera (beta S95 100h), but I couldn't get setting the mode by "_SetCurrentCaptureModeType(canonmode);" to work. I found the propcase values were wrong, and fixing them I can now read the value and match it with the right hackkey, but setting is a no go.

This isn't currently integrated with scripting or set by the GUI, but it could be setup that way. Here's my modifications to my <camera>/kbd.c

up top in the header:
Code: [Select]
static CapturemodeMap mode_dial_map[] = {
{ 0          , 0x00000000 }, // saving canonmode and canonmode for physical dial setting here.
{ 0          , 0x00000000 }, // saving override settings here.
{ MODE_AUTO  , 0x0000000f }, // Same as mask for my camera, but not sure if this is always the case.
{ MODE_P      , 0x00000007 },
{ MODE_TV    , 0x00000005 },
{ MODE_AV    , 0x00000004 },
{ MODE_M      , 0x00000006 },
{ MODE_C      , 0x00000003 }, // previously unlisted - why?
{ MODE_BLANK , 0x00000009 }, // previously unlisted
{ MODE_VIDEO_STD , 0x0000000d },
{ MODE_SCN    , 0x0000000c }, // previously unlisted as in use a submode is actually selected
{ MODE_LOWLIGHT  , 0x0000000e },
{ 0, 0 }
};
// previously unlisted modes should be added in modelist.h

#define MODE_REG 1

#define KBD_MODE_SET    mode_dial_map[0]
#define KBD_MODE_OVERRIDE  mode_dial_map[1]
#define KBD_MODE_AUTO    mode_dial_map[2]
#define KBD_MODE_P      mode_dial_map[3]
#define KBD_MODE_TV      mode_dial_map[4]
#define KBD_MODE_AV      mode_dial_map[5]
#define KBD_MODE_M      mode_dial_map[6]
#define KBD_MODE_C      mode_dial_map[7]
#define KBD_MODE_BLANK  mode_dial_map[8]
#define KBD_MODE_VIDEO_STD  mode_dial_map[9]
#define KBD_MODE_SCN    mode_dial_map[10]
#define KBD_MODE_LOWLIGHT   mode_dial_map[11]

The code itself:
Code: [Select]
int set_mode_dial(int set_hackmode)
{
int i = 2;  // 0 and 1 are used to hold set and override values
while (mode_dial_map[i].canonmode){ //runs till the end -{0,0}
if (mode_dial_map[i].hackmode == set_hackmode) { //find what's set
KBD_MODE_OVERRIDE.canonmode = mode_dial_map[i].canonmode;
KBD_MODE_OVERRIDE.hackmode = mode_dial_map[i].hackmode;
return 1;
}
i++;
}
return 0;
// takes time to go into effect, so be sure to wait until mode is finished changing.
// change will hold until mode dial is moved or camera restarted.
}

int check_set_mode_dial()
{
return KBD_MODE_SET.hackmode;
}

int check_override_mode_dial()
{
return KBD_MODE_OVERRIDE.hackmode;
}

void my_kbd_read_keys()
{
static long i=0;
int temp;

kbd_prev_state[0] = kbd_new_state[0];
kbd_prev_state[1] = kbd_new_state[1];
kbd_prev_state[2] = kbd_new_state[2];

_GetKbdState(kbd_new_state);

// Mode dial override
temp = kbd_new_state[MODE_REG] & KBD_MODE_AUTO.canonmode; //save old dial position - using auto as the mask
if (KBD_MODE_SET.canonmode != temp) {  //has the dial moved?
i = 2;  // 0 and 1 are used to hold values
while (mode_dial_map[i].canonmode){  //runs till the end {0,0}
if (mode_dial_map[i].canonmode == temp) { //find what's set
KBD_MODE_SET.canonmode = mode_dial_map[i].canonmode;
KBD_MODE_SET.hackmode = mode_dial_map[i].hackmode;
break;
}
i++;
}
// this is my own overrides, something different should be done here. Maybe gui control or just set like the default case.
switch (KBD_MODE_SET.hackmode) {  //find override
case MODE_AUTO:
KBD_MODE_OVERRIDE.hackmode = KBD_MODE_P.hackmode; // I don't like auto mode
KBD_MODE_OVERRIDE.canonmode = KBD_MODE_P.canonmode;
break;
case MODE_BLANK:
case MODE_LOWLIGHT:
case MODE_SCN:  //someday will make these do something interesting
KBD_MODE_OVERRIDE.hackmode = KBD_MODE_M.hackmode;
KBD_MODE_OVERRIDE.canonmode = KBD_MODE_M.canonmode;
break;
default:
KBD_MODE_OVERRIDE.hackmode = KBD_MODE_SET.hackmode;
KBD_MODE_OVERRIDE.canonmode = KBD_MODE_SET.canonmode;
}
}
// needs to be set in every my_kbd_read_keys() pass.  Again using auto as the mask.
kbd_new_state[MODE_REG] = (KBD_MODE_OVERRIDE.canonmode | (kbd_new_state[MODE_REG] & ~KBD_MODE_AUTO.canonmode));

// Below this is unmodified
if (kbd_process() == 0) {
// leave it alone...

I'm also working on a key mapping override, and that in combination with this hack we can make our own custom modes.  I'm not sure how to make this universal as many camera's don't have a physical dial, but maybe someone has some ideas?  Also, How does setting by propcase work?

*

Offline reyalp

  • ******
  • 12364
Re: Mode dial overriding
« Reply #1 on: 02 / September / 2011, 20:50:39 »
Quote
I don't know if it's just my camera (beta S95 100h), but I couldn't get setting the mode by "_SetCurrentCaptureModeType(canonmode);" to work. I found the propcase values were wrong, and fixing them I can now read the value and match it with the right hackkey, but setting is a no go.
Does the capmode test script work ? If so, you did something wrong. If not, then there's something wrong with the port.
Quote
I'm not sure how to make this universal as many camera's don't have a physical dial, but maybe someone has some ideas?
The whole reason we use a software approach (SetCurrentCaptureModeType) rather than overriding physw bits is that there's no portable way to do the latter.

Even on cameras that have a physical mode selector, there are often modes that are only selectable in software. Supporting all the variations of ~70 different cameras would be a huge amount of work, and probably require significant re-writing to do sanely.

I don't think you should be using the modelist.h values for what you are trying to do. Those strictly represent modes which can actually be set (except for some video mode stuff that is a result of previous mistakes)

C mode also doesn't really fit cleanly into this, because the propcase we use to get the current mode reflects the actual mode that was saved for C. There is another propcase that reports whether C was selected.
Quote
Also, How does setting by propcase work?
I don't understand. You cannot set the mode by propcase. SetCurrentCaptureModeType uses the same values as the propcases.

Some history of the existing mode switching code may be found in this thread http://chdk.setepontos.com/index.php?topic=3228.msg44427#msg44427
Don't forget what the H stands for.

Re: Mode dial overriding
« Reply #2 on: 03 / September / 2011, 03:09:33 »
My intention wasn't to make a new way to set the mode, but to read the dial selection and to make unused modes instead select do something useful (our own C modes). I first tried setting by SetCurrentCaptureMode and failed - I'll have to reinvestigate that.

Modelist.h is a list of all the modes that can be set on all the various cameras.  Most the list is invalid for one particular camera, so I fail to see the difference there. Although I do agree it should be a #define instead of in the enum if its only used in C.

That thread explains a lot I was wondering about. You have a list of threads with good info of how CHDK works somewhere?

*

Offline msl

  • *****
  • 1266
  • A720 IS, SX220 HS 1.01a
    • CHDK-DE links
Re: Mode dial overriding
« Reply #3 on: 03 / September / 2011, 03:40:42 »
Modelist.h is a list of all the modes that can be set on all the various cameras.  Most the list is invalid for one particular camera, so I fail to see the difference there. Although I do agree it should be a #define instead of in the enum if its only used in C.
Use a Lua script in conjunction with capmode.lua and you can get a valid mode list of your camera. This method works fine e.g. with ptpCamGui. For special things is a Lua script always a good way.

msl
CHDK-DE:  CHDK-DE links


Re: Mode dial overriding
« Reply #4 on: 07 / September / 2011, 14:27:11 »
Yep, I messed it up the first time around. Here is a improved version. 
Code: [Select]
//////////////////////////////

// Our physical mode dial switch values. If scripts are to access this then something different will need to happen here
#define MODE_DIAL_A 0x0000000f
#define MODE_DIAL_P 0x00000007
#define MODE_DIAL_TV 0x00000005
#define MODE_DIAL_AV 0x00000004
#define MODE_DIAL_M 0x00000006
#define MODE_DIAL_C 0x00000003
#define MODE_DIAL_BLANK 0x00000009
#define MODE_DIAL_VIDEO 0x0000000d
#define MODE_DIAL_SCN 0x0000000c
#define MODE_DIAL_LOWLIGHT 0x0000000e

// Put your overrides in here, name the hackmode what you want it to select.
static CapturemodeMap mode_dial_map[] = {
 // { hackmode      ,  canonmode }  // canonmode for the physical mode dial
{ 0          , 0x00000000 }, // saving selected mode here.
{ MODE_P , MODE_DIAL_A }, // Auto
{ MODE_P     , MODE_DIAL_P },
{ MODE_TV    , MODE_DIAL_TV },
{ MODE_AV    , MODE_DIAL_AV },
{ MODE_M      , MODE_DIAL_M },
{ MODE_P      , MODE_DIAL_C },
{ MODE_M , MODE_DIAL_BLANK },
{ MODE_VIDEO_STD, MODE_DIAL_VIDEO },
{ MODE_M    , MODE_DIAL_SCN },
{ MODE_M , MODE_DIAL_LOWLIGHT },
{ 0, 0 }
};

#define MODE_DIAL_REG 1
#define MODE_DIAL_SET    mode_dial_map[0]
#define MODE_DIAL_AUTO    mode_dial_map[1]  // utilizing this for mask, may not work this way in all cameras

/////////////////////////////////////////

// Mode dial override
temp = kbd_new_state[MODE_DIAL_REG] & MODE_DIAL_AUTO.canonmode; //get new dial position - using auto as the mask
if (MODE_DIAL_SET.canonmode != temp) {  //has the dial moved?
i = 1;  // 0 is used to hold values
while (mode_dial_map[i].canonmode){  //runs till the end {0,0}
if (mode_dial_map[i].canonmode == temp) { //find what's set and it's override
MODE_DIAL_SET.canonmode = mode_dial_map[i].canonmode;
MODE_DIAL_SET.hackmode = mode_dial_map[i].hackmode;
break;
}
i++;
}
/*switch (MODE_DIAL_SET.canonmode) {  //make these do something interesting - Our own C modes!
case MODE_DIAL_A:
case MODE_DIAL_BLANK:
case MODE_DIAL_LOWLIGHT:
case MODE_DIAL_C:
case DIAL_MODE_SCN: 
} */
}
// the camera detects when the switch status changes, so needs to be set in every my_kbd_read_keys() pass.
kbd_new_state[MODE_DIAL_REG] = (MODE_DIAL_AUTO.canonmode | (kbd_new_state[MODE_DIAL_REG] & ~MODE_DIAL_AUTO.canonmode));

if (MODE_DIAL_SET.hackmode != (mode_get() & MODE_SHOOTING_MASK))
shooting_set_mode_chdk(MODE_DIAL_SET.hackmode);
//////////////////////////

Side effect of setting by "shooting_set_mode_chdk()" is there is not couple seconds wasted by canon's splash when changing modes, but now there is no canon "C" mode, only our hacked modes we can add. I did notice prop 50 holds a special value in C mode (otherwise is always the same as 49), maybe there's is a way to set to C?

This obviously isn't finished as it should be an option in the menu, an speaking of which, how could should the gui go for this?  Also, a way to read the dial while in script mode needs to be added and disabling it while a script is running.

What's everyone think?

 

Related Topics