Thursday, 30 October 2014

Dead ScoutGuard & bargain Bushnell

Any plans I had for hacking the ScoutGuard came to an abrupt end recently when this happened:

Yes, I managed to not only lift the track off the PCB but also break the pin off the PIC. The camera was misbehaving quite badly before this incident anyway and I was getting close to calling it a day but this is one of those annoying mistakes that forced my hand. There is still sufficient track left to tap into, it is the minimal pin leg on the PIC that is the real issue.
In an attempt to keep the project going I had a look on ebay in the hope of finding someone getting rid of a similar camera that I might be able to salvage the PIC out of. No luck, although I did stumble on a Bushnell Trophy Cam model 119436 with the description Not working for repair/parts or use as a dummy camera”. I ended up winning with a bid of £21 (new ones, despite the 119436 being a 2011 model, go for around £125+ so it was worth the gamble). 

When the camera turned up I hooked it up to the power supply but there were no signs of life. I opened up the case, half expecting the electronics to be missing, hooked up the power again in preparation to check the supply rails and the camera came to life! I put the case back on, inserted an SD card and checked the functionality. Surprise surprise, it all seemed to be working fine. I'm not quite sure what the issue was but luckily it didn't appear to be serious. 

A quick look at the inners shows that the Bushnell design makes use of BGA components unlike the ScoutGuard and it also uses the same PIC16F684, although in the Bushnell it is mounted on a sort of riser board. The use of the riser board isn't clear to me, perhaps they offer different trigger mechanisms on different models and this was the easiest way to do it? The use of the same PIC perhaps doesn't come as too much of a surprise after I eventually found out that Bushnell and ScoutGuard are apparently made by the same company



A few interesting points on the back of the board:

Serial console

Bed of nails test pads. The connector to the left of the pads is where the flex cable for the UI plugs into and the pads are hooked up directly to the individual pins. 

Untested theory, but could the lower pads in the red box be JTAG? They head into the processor. A potential investigation for another day, but the pads are pretty small so I'm not so keen to try and interface to them.

While the ScoutGuard used an ARM processor, the Bushnell processor is a MIPS, and quite probably a Zoran SoC (thanks Graham).  

Like the ScoutGuard, there is a UART that not only spits out plenty of debugging info but also provides a number of commands on what presumably must be a Zoran authored OS. The output can be seen at the end of this post.

Luckily for me, the Bushnell also inserts a logo into each image so my original ScoutGuard goal of hacking the firmware to remove that feature is still on. The first stage will be to try and find the functionality in the code.

Anyway, here is the dump from the serial terminal.
FB load wav failed

THR HcePreBoot
Hce proc started
hMsg = 830
THR SectionInit
MON> THR2 - Monitor
THR2 - AgentServer

Boot (fast) - VER: HW=0x11B0, FW=0x1101.041D.10A2, CMP=0x112, FRQ=162000000, CFG=0x27
THR HcePreBoot
HCE Ver = Nov 13 2010, 15:10:41
IP  Ver = Mar 18 2009, 19:57:45
P4 CL # =  112701
Size of Section 1 = 538524 bytes
Size of Section 2 = 1035796 bytes
Size of Section 3 = 1179016 bytes
Size of Section 4 = 1454828 bytes
CODE = 4208212 bytes, DATA = 228393 bytes, DRAM = 67108864 bytes (64 MB)
run here 070601!
Toppoly LCD initialization!!
Load Gamma 2 OK
GdiLoadFont - \Font\COMIC.BIN
wMediaType = 0
fx_media_available_clusters = 42 fx_media_bytes_per_sector= 512 fx_media_sectors_per_cluster=32
dir = 100 , file = 2
Resident media mounted successfully (22 mSec).
DCF DB created succesfully (22 mSec).
H=0, L=0
Ir cut on!
R(185,400) B(292,465)
ulAwbLutSize(Gr,Gb) = (57,51)
AwbSetMode 16

AppSetMode 0x0 -1
:::HCE Wait For Msg Id 800
:::HCE Wait For Msg Id 800
:::HCE Wait For Msg Id 800
:::HCE Wait For Msg Id 800
:::HCE Wait For Msg Id 800
battery level changed! old=196, new=217
:::HCE Wait For Msg Id 800
:::HCE Wait For Msg Id 800
:::HCE::: Target Msg 800 Received with Param 0
through idle mode
AppSetMode 0x30 1
:::HCE Wait For Msg Id 800
:::HCE Wait For Msg Id 800
:::HCE Wait For Msg Id 800
:::HCE Wait For Msg Id 800
:::HCE Wait For Msg Id 800
:::HCE Wait For Msg Id 800
:::HCE Wait For Msg Id 800
:::HCE::: Target Msg 800 Received with Param 30
:::HCE::: PreviousHCEMode to 0 mode
:::HCE::: ChangeHCEMode to 2 mode
sSStillState.uwImageSize is 1
I43_SetImageSize - OK
AwbSetMode 16
R(185,400) B(292,465)
ulAwbLutSize(Gr,Gb) = (57,51)
AwbSetMode 16
H=0, L=0
R(185,400) B(292,465)
ulAwbLutSize(Gr,Gb) = (57,51)
AwbSetMode 16
GdiLoadFont - \Font\StaFont.BIN
GdiLoadFont - \Font\COMIC.BIN
AppSetMode 0x40 -1
StillOnActive -1
THR AaaAwb
THR AaaAwb1
THR AaaHist
:::HCE Wait For Msg Id 800
THR PreviewMode
THR StillPreviewDistServMain
THR Sensor
:::HCE::: Target Msg 800 Received with Param 40
THR StatAe
ulBackgroundColor 0x80008000
still constr over!
Ir cut off!
R(185,400) B(292,465)
ulAwbLutSize(Gr,Gb) = (57,51)
AwbSetMode 16
R(185,400) B(292,465)
ulAwbLutSize(Gr,Gb) = (57,51)
AwbSetMode 16
MON> help
help -- Prints function help
ls -- Prints all avaliable functions help
quit -- Quits the monitor
prompt -- Set new prompt
repeat -- Repeate a cmd command num times with a delay between (ms)
set_media -- Choose media types
smed -- Choose media types
format -- Format a media
mount -- Mount a media
mountx -- Mount a media
mountdram -- Create and Mount Dram media
flush -- Flush the media
gms -- Get media status
goms -- Get Other media status
delall -- Delete all DCF objects
delete -- Delete an object
lock -- Lock an object
unlock -- Unlock an object
copy -- Copy an object
move -- Move an object
copyto -- Copy an object to another drive
dcfdump -- DCF dump
cfread --
ideread --
ataread --
sdread --
msread --
ssfdcread --
nandread --
nandreadp --
nandnsread --
noraread --
noriread --
cd -- Change directory
cdc -- Change dir to first DCF folder
dir -- List directory's contents
ren -- Renames a file/directory
mkdir -- Create a directory
del -- Delete a file/directory
cfflush -- Flushes contents into file
msflush -- Flushes contents into file
msflushp -- Flushes physical contents into file
nandflush -- Flushes contents into file
nandnsrflush -- Flushes contents into file
burstmode -- Switches read operations mode
msextra -- Flushes extra bytes into file
nandextra -- Flushes extra bytes into file
ssfdcextra -- Flushes extra bytes into file
cferase -- Erase CF sectors
nanderase -- Erase the whole Nand media
ssfdcerase -- Erase the whole SSFDC media
norerase -- Erase the whole Nor media
ssfdcreadp -- Read physical sectors
ssfdcwritep -- Write physical sectors
nandwritep -- Write physical sectors
ssfdcreset -- Reset SSFDC
msreadp -- Read physical sectors
norreadp -- Read physical sectors
cfwrite -- Write sectors
atawrite -- Write sectors
atadma -- Enable/Disable uDma mode
nandimg -- Burn image file as-is to nand
nandid -- NAND read ID
nandr -- NAND read data
nandw -- NAND write data
nandrs -- NAND read spare data
nandws -- NAND write spare data
cr -- Set compression ratio
ei -- Edit Image
getexp -- Get exposure/gain
setexp -- Set current exposure
wbs -- Set WB scalers
wbg -- Get WB scalers
wbm -- Set AWB mode
aem -- Set AE mode
afwinget -- Get window AF values
afwinset -- Set window AF dimensions
wbcalib --
stat -- Set statistics pattern
statdebug -- Print statistics on/off
algtime -- Print algorithms time statistics
aecfg -- Set AE configuration
ssw -- mode left top width height
setpixel -- on R Gr B Gb
sis -- mode width height
motor_shutter -- 0 - open;   1 - close
motor_iris -- 0 - big;   1 - small
sony_iris -- move iris motor (o - open, c - close)
fh -- Move focus to home position
fmove -- Move focus
fs -- Search for correct focus position
fm --
zhome -- Move zoom to home position
zmove -- Move zoom
zmanual --
emanual --
lens_open --
strobe --
sp -- send TG(0)/AGC(1) sp data
spsharp -- send TG(0) sp data
getsharptg -- Get TG sp data
sdadsharp -- Search adclk sharp phase
sddksharp -- Search dclk sharp phase
agcsp --
sdsp --
sdspfine --
zm --
focus_temp --
sonysp --
j_test -- get edge info
faf_mode -- set faf mode
gpioset --
sonyphase --
sz --
rg -- Read 16bit GPP RAM address
fc -- Call a function
sum -- I43_SetUsbMode
hqd -- Host queue dump
casio -- Switch to Casio LCD
dlcd -- Switch to DLCD
ntsc -- Switch to TV Ntsc
pal -- Switch to TV Pal
hd -- Switch to HD
hdf -- Switch HD format
viewc -- View on LCD
setp -- Set parameter
getp -- Get parameter
mode -- Set functional mode
modeconf -- Select mode configuration
cc -- I43_ConfigCapture
cm -- I43_ConfigMovie
cp -- I43_ConfigPreview
ttcop -- Dump thread table
tcresetcop -- Reset thread counters
txtcop -- Dump threadX table
tmrtcop -- Dump timer table
qtcop -- Dump queue table
qicop -- Dump queue info
etcop -- Dump events table
smtcop -- Dump mutex and semaphore table
tt -- Dump thread table
tcreset -- Reset thread counters
txt -- Dump threadX table
tmrt -- Dump timer table
qt -- Dump queue table
qi -- Dump queue info
et -- Dump events table
smt -- Dump mutex and semaphore table
isrt -- Dump ISRs table
playerdump -- Dump player info
getsr -- Dump status registers Sr1 & Sr2
cgut -- Dump CGU table
smdbdump -- Dump SMDB database
mips -- Get available MIPS
mipscop -- Get available MIPS
cpu -- Print CPU load statistics
ver -- Get version number
prof -- Profiling tool
cmdcr -- Command file create
cmdex -- Command file execute
delay -- Delay in ms (in a command file)
sci -- I43_SetCurrentImage
gci -- I43_GetCurrentImage
gcii -- I43_GetCurrentDirImage
wav -- Play Wav file
mp3 -- Play MP3 file
pcc -- I43_PlaybackClipCommand
mpeg4 -- Switch to MPEG4 video
wmv -- Switch to WMV video
mp4 -- Switch to MPEG4 video with AAC audio
h264 -- Switch to H264 video
visbus -- Set Visbus Mode
tape -- TapeRecorder
wmvm -- Switch to WMV main profile
le -- Print the last error number
photoframe -- Add photo-frame to captured images
ccc -- I43_CaptureClipCommand
rrs -- Read Register Shadow
wrs -- Write Register Shadow
c2ccalib -- C2C calibration
imagesize -- Set image size
timing --
rfstest -- Test read File
wfstest -- Test write File
g -- Start PWR consumption prints
cgucfgen -- Configure and Enable Clock
cgudis -- Disable Clock
rosc -- Get CGU ring oscillator counters
tlb --
rsgop -- Set gop size of recorded clips
rsmaxb -- Set max b frames of recorded clips
mtmstart -- Initialize timing mark of movie group
mtmstop -- Dumps timing mark of movie group
pwrtime -- Time power state for <ms>,dump results to <fileName>
addmulticonfig -- Add configuration for Usb multi mode
fdprepare -- Prepare preview for face detection
fd -- Enable/Disable/TestMode face detection
fdtmstart -- Initialize timing mark of FDTA group
fdtmstop -- Dumps timing mark of FDTA group
fdd -- Dumps timing mark of FDTA group
custom -- Print the input numbers
trans --
tkill -- Exit transcoder
tgop -- Set transcoder gop size
tsaP -- Set transcoder P frame search area
tsaB -- Set transcoder B frame search area
text -- Set transcoder file extension
trb -- Set max b frames
tvbr -- Set constant quality scalers
tcbr -- Set constant bitrate value
twin -- Set brc window size
tcnst -- Set const frame type
trate -- Set conversion rate
tsb -- Enable/Disable stabilizer
tmode -- Set transcoder mode
tbrc -- Set bitrate level control
atrans --
tscodec -- Set codec (mpeg4/mpeg2/wmva/wmvm)
tsvlc -- Set vlc table (ac/dc/mvd/cbp)
tcq -- Set constant bitrate value
tinsize -- Set constant bitrate value
gstab --
gskill -- Exit GStabilizer
gsgop -- Set GStabilizer gop size
gssaP -- Set GStabilizer P frame search area
gssaB -- Set GStabilizer B frame search area
gsext -- Set GStabilizer file extension
gsrb -- Set max b frames
gsvbr -- Set constant quality scalers
gscbr -- Set constant bitrate value
gswin -- Set brc window size
gscnst -- Set const frame type
gsrate -- Set conversion rate
gsbrc -- Set bitrate level control
gscodec -- Set codec (mpeg4/mpeg2/wmva/wmvm)
gsvlc -- Set vlc table (ac/dc/mvd/cbp)
gscq -- Set constant bitrate value
gsinsize -- Set constant bitrate value
aplay -- AudioPlay
astop -- AudioStop
sdioi -- SDIO card init 1BIT/4BIT
sdiori -- SDIO card read info
sdiorc -- SDIO card read common CIS
sdiosb -- SDIO card switch bus width
sdiowr -- SDIO card write register
sdiorr -- SDIO card read register
sdiowm -- SDIO write multi bytes
sdiorm -- SDIO read multi bytes
sdiowmb -- SDIO write multi blocks
sdiormb -- SDIO read multi blocks
sdioset -- SDIO read set block size
sdioget -- SDIO read get block size
sdiow -- SDIO wait interrupt
dummy -- Print the input numbers
aviplay -- Test Pin
avistop -- Test Pin
avipause -- Test Pin
avifw -- Test Pin
avibw -- Test Pin
image -- Test Pin
SaveOption -- SaveOption
DpsAddImage -- DpsAddImage
DpsConfig -- DpsConfig
DpsAction -- DpsAction
Wdm -- Set USB Mode to WDM
cfggpio -- config gpio
selgpio -- config gpio
setgpio -- config gpio
hcedeletefile -- DeleteFile
hcelockfile -- Lock File
hceulockfile -- UnLock File
hcecopyto -- copyto
wav --
layer --
usb --
pccame --
msdc --
mic --
AUW --
dmwt --
dmrd --
XX --
pwr --
mp4sk --
gma --
sma --
rand --
xz8802reset --
xz88021 --
xz88022 --
xz88023 --
xz88024 --
xz88025 --
i2cr -- test i2c
i2cw -- test i2c
wakeup -- test wakeup
rl -- Read 32 bit address
wl -- Write 32 bit address
mf -- Fill memory with a value
rv -- Read a variable value or array index
wv -- Write a variable value or array index
dump -- Dump memory to screen
dumpx -- Dump DRAM to screen. Hex Input
dumpf -- Dump memory to file
dramsize -- Print dram size
mi -- Get Max Alloc Size
mt -- Dump Alloc table
mxt -- Dump pool structure
ldstart -- Start leak detection
ldstop -- Dump leaks
hmpp -- Hardware memory protection (physical address)
hmpv -- Hardware memory protection (only virtual address accesses)
hmpoff -- Turn off hardware memory protection
cache -- Cache debug
cachecop -- Cache debug on COP
runlocked -- Run function locked in cache (Code+stack)
pwridle01 -- leakage measurements    
pwridle02 -- cgu sleep mode          
pwridle03 -- cgu deep sleep mode      
pwridle04 -- default idle mode        
pwridle05 -- idle mode no dac        
pwridle06 -- idle:cpu,mmu,ker,uart    
pwridle07 -- idle:cpu,mmu,ker        
pwridle08 -- sp:cpu wrk, ker          
pwridle09 -- sp:cpu stk, ker          
pwridle10 -- sp:cpu wrk, ker, mmu    
pwridle11 -- sp:cpu stk, ker, mmu    
pwrview -- view mode no dac        
pwrmpeg1 -- mpeg4 rec: no aud, no Dvs
pwrmpeg2 -- mpeg4 rec: w/ aud, no Dvs
pwrmpeg3 -- mpeg4 rec: w/ aud, no Dvs
pwrmpeg4 -- mpeg4 rec: w/ aud, no Dvs
pwrmjpeg1 -- mjpeg rec: no aud, no Dvs
pwrmjpeg2 -- mjpeg rec: w/ aud, no Dvs
pwrstill -- capture and playback still
pwrfd -- view with FD enabled    
pwrdist -- view with DIST enabled  
pwrplaymov -- play cur movie from sd
pwrruntest -- run all tests
pwrkillall -- kills all unnecessary units
pwrcgusleep -- Puts the CGU to sleep
pwrcguon -- CguUnitOn
pwrcguoff -- CguUnitOff
pwrcguoffall -- CguAllUnitsOff
pwrtest -- Test Power
pwrsetexp -- Sets exposure
pwruseosd -- Determins if OSD is used
pwruselpd -- Determins if low pwr demosaic is used
pwruselpc -- Determins if low pwr cylpf is used
MON> battery level changed! old=217, new=220


  1. Hi Billy, thanks for posting this information about the Bushnell. I am trying to hack my own Bushnell to see if I can tap the PIR motion sensor and bring it to my arduino. I can directly tap into the PIR sensor, but I rather want to tap into the point where it is filtered already and provides me with a simple on/off state. Do you know at what point/pin I need to do this? If needed I can post an image of the pcb. Would be great!

  2. Replies
    1. Hi Tim, I think unfiltered data is being consumed by the pic, same as you have done with your arduino and depending on the sensitivity mode set in the UI the code on the pic will decide on the threshold level. I can't remember, but the bushnell might activate an LED when it takes a shot which might give you what you want? But if you are already reading the PIR it would be best to just implement the check manually.

    2. Hi Billy, thanks. I have found 3 pins on the pic that switxh between 0 and 3.3 Volt whenever I trigger the motion/pir sensor. Will I be able to just read one of them with a digital pin on my arduino sending on/off or is it still analog?

    3. Do you have an oscilloscope you can check with? If not, just give it a go with digitalRead, it would be unlikely to cause any damage if you are just reading it.

  3. Hi Billy, stumbled upon this old post of yours. I have a friend who would like to be able to trigger his wireless bushnell camera using an arduino. At the moment, it will only send pictures wirelessly when motion is triggered. No other method will send pictures wirelessly. He'd like to be able to trigger on a schedule, once a day, so that he can see what the weather is like on his property. (He's even engaged the support folks at bushnell to add the feature but no luck. They are not interested.) Any thoughts on how to simulate the motion trigger? I don't have a camera in hand yet, but I had thought about trying to work up a command sent via serial, or triggering a pin like the one Tim was looking to read. I'm hopeful that maybe the signalling between the sensor and rest of the board is really simple?

    1. It should be fairly straight forward, the trick is finding the trigger pin. I don't have a camera to probe about with but what I'd be tempted to try is looking for one of the pins on the PIC (assuming the newer cameras still use PICs and the pins are accessible) that changes state when the camera is triggered. If you have an oscilloscope then this should be relatively easy, if not you might need to build a simple logic probe using an LED. If you can get some high res images of the board you can email them to reversatronics at gmail dot com and I'll have a look.

    2. Thanks for the reply Billy! I don't have an oscilloscope anymore, but I do have a Saleae Logic that would probably work. I bought ages ago but haven't had a need to use it yet.