shooting script using Canon basic ? - page 3 - General Discussion and Assistance - CHDK Forum  

shooting script using Canon basic ?

  • 82 Replies
  • 48808 Views
*

Offline srsa_4c

  • ******
  • 4451
Re: shooting script using Canon basic ?
« Reply #20 on: 12 / September / 2018, 14:13:20 »
Advertisements
I've formatted a 64G card to FAT32 and done:
  • echo -n SCRIPT | dd bs=1 count=6 seek=496 of=/dev/mmcblk0
  • then created script.req and extend.m
The script consists of 2 parts:
extend.m is for starting the longer script which should be in a file named autotest.m .
The extend.m script alone won't do anything visible.

Re: shooting script using Canon basic ?
« Reply #21 on: 12 / September / 2018, 14:23:13 »
sorry for the confusion, I was testing the "hello word". ...got it working finally; I've originally wrote the boot sector on the device block instead on the partition.

Your script works perfectly!  ...take 3 pictures and write a set of orange texts in the top left corner.  The only thing, I can only run the script once; I need to re-start the camera to get it working again.

I can run the script multiple times in record mode with SET + right; the sequence is executed (orange texts displayed) but the camera doesn't take any picture. Under this mode, the camera stays in the SET menu during the execution and exits back to record mode when the script terminates.

...another thing; with these changes when the camera goes to sleep then you can't resume it with a button press (only the shutter button works)
« Last Edit: 12 / September / 2018, 14:39:36 by cedricb »

*

Offline srsa_4c

  • ******
  • 4451
Re: shooting script using Canon basic ?
« Reply #22 on: 12 / September / 2018, 16:40:56 »
Your script works perfectly!  ...take 3 pictures and write a set of orange texts in the top left corner.
Okay, that's good news.
Quote
The only thing, I can only run the script once; I need to re-start the camera to get it working again.
Don't worry about that, this script is really just proof of concept.
Quote
I can run the script multiple times in record mode with SET + right; the sequence is executed (orange texts displayed) but the camera doesn't take any picture. Under this mode, the camera stays in the SET menu during the execution and exits back to record mode when the script terminates.
This way, you're only running the second part of the script in a limited mode that was mentioned previously - it's normal that it doesn't work well.
Quote
...another thing; with these changes when the camera goes to sleep then you can't resume it with a button press (only the shutter button works)
Does this also happen if you only execute the script once (from playback mode)?


The next step is to do some research (tech details follow).
(1) find a way to interact with the script
(2) find out how to access the (exposure & other) controls

For (1), my current ideas are
- snooping the button states by reading physw_status
- using IsControlEventActive
... neither of which allows masking the buttons so the firmware will know they were pressed

For (2), exposure compensation should be accessible as UI property, but many other exposure controls are likely not. Last resort is using button and dial events .

I'll post research scripts next (will probably take a few days).

Side note: most of our scripts on wikia (dumpers and the rest) are flawed:
event procedures will get random values for arguments that are not provided by the caller. For example, LCDMsg_Create has 3 or 4 arguments, one of which is a pointer...

*

Offline srsa_4c

  • ******
  • 4451
A few Canon Basic discoveries
« Reply #23 on: 14 / September / 2018, 12:40:16 »
- A public function automatically becomes an event procedure.
- CreateProxyOfEventProcedure creates a native wrapper for the specified eventproc (meaning the proxy uses the firmware's calling convention). In the firmwares I checked, 20 such proxies can be created.
Combining the above two, it's possible to make a task in CBasic.
Keyboard can be intercepted by creating a controller and making it top level.

Following test script displays logical events passed to the UI (it's hard to read, but I could not come up with a better way to display). 16 events are displayed (4x4), first event is the most recent.
The script should run on newer cams.
Code: [Select]
dim inited=0, startcnt=0
dim disp0, disp1, disp2, disp3, disp4, msgstr
dim chandle=0, cncall=0, cbuf
dim dbg2=0, dbg1=0, plug=1, alt=0

public function mycontroller(p1, p2, p3)
    cncall = cncall + 1
    ' fifo for events
    for n=0 to 14
        m = 14-n
        m = m * 4
        nn = 15-n
        nn = nn * 4
        Poke32(cbuf + nn, Peek32(cbuf + m))
    next
    Poke32(cbuf, p2)
    ' return code 0 = events are swallowed here, 1 = events are passed on to the rest of UI
    mycontroller=1
end function

private sub myinit()
    'System.Create() ' already done in Initialize
    UI.Create() ' for named button events and more
    'UI.CreatePublic() ' UI.Create makes this redundant
    SS.Create() ' PT_ eventprocs for capt_seq feedback, and more
    'ExportToEventProcedure("unregevproc",0xFF889100) ' not an eventproc on newer cams, addr is cam specific
    msgstr = AllocateMemory(40 * 5)
    cbuf = AllocateMemory(32 * 4)
    disp0 = LCDMsg_Create(10,1,"Init",2)
    disp1 = LCDMsg_Create(10,41,"1",2)
    disp2 = LCDMsg_Create(10,81,"2",2)
    disp3 = LCDMsg_Create(10,121,"3",2)
    disp4 = LCDMsg_Create(10,161,"4",2)
    LCDMsg_ChangeColor(disp0, 2)
    adr=CreateProxyOfEventProcedure("mycontroller")
    chandle = CreateController(adr, 0) ' 2nd param 0 or 1, meaning unknown
    MoveControllerToTopOfZOrder(chandle)
end sub

private sub myuninit()
    DeleteController(chandle)
    DeleteProxyOfEventProcedure("mycontroller")
    DeleteProxyOfEventProcedure("mytask")
    LCDMsg_Delete(disp0)
    LCDMsg_Delete(disp1)
    LCDMsg_Delete(disp2)
    LCDMsg_Delete(disp3)
    LCDMsg_Delete(disp4)
    FreeMemory(msgstr)
    FreeMemory(cbuf)
end sub

private sub redraw(row)
    ' string length is limited (32 on a3200), FAILED is displayed when too long
    if row = 0 then
        LCDMsg_SetStr(disp0,msgstr)
    end if
    if row = 1 then
        LCDMsg_SetStr(disp1,msgstr+40)
    end if
    if row = 2 then
        LCDMsg_SetStr(disp2,msgstr+40 * 2)
    end if
    if row = 3 then
        LCDMsg_SetStr(disp3,msgstr+40 * 3)
    end if
    if row = 4 then
        LCDMsg_SetStr(disp4,msgstr+40 * 4)
    end if
end sub

public function mytask()
    myinit()
    cyc=0
    prevcnt=0
    curcnt=cncall
    do while plug=1
       Wait(100)
       if curcnt<>prevcnt then
           sprintf(msgstr,"Controller called: %d",cncall)
           sprintf(msgstr+40, "%04x, %04x, %04x, %04x",Peek32(cbuf),Peek32(cbuf+4),Peek32(cbuf+8),Peek32(cbuf+12))
           sprintf(msgstr+80, "%04x, %04x, %04x, %04x",Peek32(cbuf+16),Peek32(cbuf+20),Peek32(cbuf+24),Peek32(cbuf+28))
           sprintf(msgstr+120,"%04x, %04x, %04x, %04x",Peek32(cbuf+32),Peek32(cbuf+36),Peek32(cbuf+40),Peek32(cbuf+44))
           sprintf(msgstr+160,"%04x, %04x, %04x, %04x",Peek32(cbuf+48),Peek32(cbuf+52),Peek32(cbuf+56),Peek32(cbuf+60))
           redraw(0)
           redraw(1)
           redraw(2)
           redraw(3)
           redraw(4)
       end if
       if (cyc & 4)>0 then
           MoveControllerToTopOfZOrder(chandle)
       end if
       cyc = cyc + 1
       prevcnt=curcnt
       curcnt=cncall
    loop
    Wait(1000)
    LCDMsg_SetStr(disp0,"Script finished")
    Wait(1000)
end function

public sub isloaded()
    isloaded = inited
end sub

private sub Initialize()
    if isloaded()=1 then
        startcnt = startcnt + 1
        exit sub
    end if
    inited=1
    System.Create()
    adr=CreateProxyOfEventProcedure("mytask")
    CreateTask("cbasic1", 0x19, 0x2000, adr, 0)
end sub

private sub terminate()
    ' does not execute when a task is started from this same script
    ' even if that task exits
    plug = 0
    LCDMsg_SetStr(disp0,"terminate")
    Wait(2200)
    myuninit()
end sub
This script only consists of a single file, extend.m .

edit:
script modified to display correctly on old DryOS cameras (LCDMsg can't be positioned to zero coordinates on those)
edit2:
fix controller z order adjustment regularity
« Last Edit: 16 / September / 2018, 11:26:53 by srsa_4c »


Re: A few Canon Basic discoveries
« Reply #24 on: 15 / September / 2018, 04:16:41 »
...it works pretty well; it's well integrated into the camera firmware!   ...does it means we can listen/capture specific events ? or just keyboard events?
Otherwise I couldn't see the execution of the terminate function.

*

Offline c_joerg

  • *****
  • 1248
Re: A few Canon Basic discoveries
« Reply #25 on: 15 / September / 2018, 08:41:01 »
The script should run on newer cams.
So not on G1x? 
M100 100a, M3 121a, G9x II (1.00c), 2*G1x (101a,100e), S110 (103a), SX50 (100c), SX230 (101a), S45,
Flickr https://www.flickr.com/photos/136329431@N06/albums
YouTube https://www.youtube.com/channel/UCrTH0tHy9OYTVDzWIvXEMlw/videos?shelf_id=0&view=0&sort=dd

*

Offline srsa_4c

  • ******
  • 4451
Re: shooting script using Canon basic ?
« Reply #26 on: 15 / September / 2018, 09:48:38 »
So not on G1x?
The script has not been coded defensively (uses only newer eventproc names). I think most DryOS cameras (minus the S5IS) should work (~2008 or newer), but I could be wrong.
edit: sx100 (2008) works

...it works pretty well; it's well integrated into the camera firmware!   ...does it means we can listen/capture specific events ? or just keyboard events?
This script is mostly a research tool that also demonstrates how to use those newly found features I mentioned.
You could for example find out which codes do the various dials (and buttons) on your camera generate. All codes are displayed in hexadecimal.

As for the "well integrated": the script uses text areas provided by the firmware (LCDMsg eventprocs). The number of these text lines is limited to 10 (older cams) or 20 (newer cams), one line can display not more than 31 or 32 characters. And they are limited to one line each.
« Last Edit: 15 / September / 2018, 11:08:01 by srsa_4c »

*

Offline srsa_4c

  • ******
  • 4451
Re: shooting script using Canon basic ?
« Reply #27 on: 18 / September / 2018, 18:00:49 »
Another test script.

Demonstrates the use of the shooting related callback event procedures. They only show the time (in msecs) they are reached during shooting.
The script also implements a simple and nonfunctional menu (long press on MENU to enter/exit).
The messages are on top on pre-D6 cameras, but they are not always visible on D6 (and probably D7) cams.
Unfortunately, I have not found a way to keep the script functional without having camera specific parts. Therefore, the script has two parts: the attached extend.m and the camera specific part that goes in a file named camspec.m .
The following is camspec.m for M6:
Code: [Select]
' camera specific plugin
' m6 100b

public sub check_compat()
    if Peek16(0xe1f20270) = 0x32c5 then
        check_compat = 1
    else
        check_compat = 0
    end if
end sub

public sub get_shf_gen()
    ' camera has the newer ssfs eventprocs
    get_shf_gen=1
end sub

public sub get_cam_keys(set,menu,up,down,halfshoot)
    ' these are the Press* event codes from the levent-table
    *set = 0x85a
    *menu = 0x82a
    *up = 0x824
    *down = 0x826
    *halfshoot = 0x9a1
end sub

Some generic notes:
- I was unable to find a way to check for the availability of an eventproc. ExecuteEventProcedure crashes the camera when called with a nonexistent eventproc name. This may have been different on old cameras.
- Loading a script that has public subs or functions makes those routines available in the caller script.


Re: shooting script using Canon basic ?
« Reply #28 on: 19 / September / 2018, 08:37:19 »
on the M6 with a native lens:  start camera --> go to play mode --> press SET --> press play to go to record --> clear the screen with info
  • lines 4, 5 and 9 are empty
  • holding the menu button crashes the camera (canon menu is stucked and need to remove the battery)
  • you should reset each counter when there is a new value, at the moment these are cumulative counters
random fresh start:
  • ComplCapModeChnge -> 9250
  • shoot half -> 22080
  • CompletePreCapt -> 22490
  • CompleteFileWrite --> 23710
  • ShootPicure --> 22520
...if the values are in milliseconds then I don't think it takes ~22s to shoot or ~9s to go from play/record

by the way, nice work!  :D
« Last Edit: 19 / September / 2018, 08:59:00 by cedricb »

*

Offline srsa_4c

  • ******
  • 4451
Re: shooting script using Canon basic ?
« Reply #29 on: 19 / September / 2018, 12:13:11 »
lines 4, 5 and 9 are empty
4 and 5 are zoom (optical and digital) related callbacks, they do not react on my M10 either (but they do on a PowerShot - when zooming). Line 9 is simply empty.
Quote
holding the menu button crashes the camera (canon menu is stucked and need to remove the battery)
Yeah, that's a bit misleading - the cam does not actually freeze. The text lines are invisible when the Canon menu is shown, so you don't see the first line that tells what to do. Just hold MENU again (or press SET) to exit that menu (I called it "ALT mode"). If you invoke it with the Canon menu already open, you get a chance to actually see it.
In the current implementation, only MENU and SET exit that mode, all other keys are swallowed (UP and DOWN moves the "cursor").
Quote
you should reset each counter when there is a new value, at the moment these are cumulative counters
I'm using the firmware's millisecond counter that starts at boot. Since not all callbacks are shooting related, displaying the absolute time makes sense (and it's simple to do).

In the meantime, I managed to apply exposure overrides (Tv only for now) on the M10 and a PowerShot. Both the CompletePreCapt and ShootPicure hooks work (though only the latter allows separate override for separate pictures when shooting in continuous mode).

Since the "propset" (see propset*.h here) of the M6 is not known, finding that out is going to be the next move. Knowing the correct propcase numbers is essential for applying overrides.

 

Related Topics