Using the DS’s hardware timers, we can generate very accurate shutter times. Setting up a timer is easy:
void timerStart(int channel, ClockDivider divider, u16 ticks, fp callback)
There are four channels available. The native clock frequency (~33513.982 kHz) can be divided (by 1, 64, 256 or 1024) and the number of clock ticks (u16, max 65,535) in a cycle can be set. Finally, a callback can be assigned to deal with timer overflow.
We generate a series of tables of ticks, dividers and multipliers (a secondary count for generating longer delays than a second or so). For a given shutter speed, we look up the timer parameters and feed them in to timerStart(). The overflow interrupte handler takes care of mulipliers and triggers the shutter controls.
Unfortunately, my camera (Olympus E-P1) has a minimum shutter speed in bulb mode of about 1/16, making the faster speeds largely useless.
Setting up the timer based on the chosen shutter speed (index into a fixed table of shutter speeds):
// set up timer. gDoingExposure = true; gTime = shutterMultiplers(entry->duration); gDelay = 65535-shutterTimes[entry->duration]; gDivider = shutterDividers(entry->duration); // open shutter. setShutterState(kFull); // start timer. timerStart(TIMER_CHANNEL, gDivider, gDelay, (fp)&timerCallback);
The timer call back decrements the multiplier (to handle larger delays) and closes the shutter when done. (Tables have been truncated to save space):
void timerCallback()
{
if(--gTime == 0)
{
// close shutter.
setShutterState(kFull);
timerStop(TIMER_CHANNEL);
gDoingExposure = false;
}
else
{
// re-start timer.
timerStart(TIMER_CHANNEL, gDivider, gDelay, (fp)&timerCallback);
}
}
Lookups for timing parameters. Some are implemented as tables, while others are functions that mimic a sparse table.
const int shutterStringsLength = 67;
const char* shutterStrings[] = {
"1/4000",
// ...
"1/640",
"1/500",
"1/400",
// ...
"1/10",
"1/8",
// ...
"0''4",
"0''5",
// ...
"2''",
"2''5",
// ...
"30'"
};
// lengths based on internal DS timer with
// frequency of ~33513.982 kHz (no prescaler)
const u16 shutterTimes[] = {
8378, // "1/4000", // ClockDivider_1
// ...
52366, // "1/640",
1047, // "1/500", // ClockDivider_64 (9)
1309, // "1/400",
// ...
52366, // "1/10",
16364, // "1/8", // ClockDivider_256 (27)
// ...
52366, // "0''4",
16364, // "0''5", //ClockDivider_1024 (33)
// ...
65457, // "2''",
40911, // "2''5", // x2 (40)
// ...
65457, // "30'" // x900
};
ClockDivider shutterDividers(int index)
{
#if LIMITED_SHUTTER_SPEED
if(index < 9)
return ClockDivider_1;
if(index < 27)
return ClockDivider_64;
if(index < 33)
return ClockDivider_256;
#endif
return ClockDivider_1024;
}
const char* dividerStrings[] = {
"ClockDivider_1",
"ClockDivider_64",
"ClockDivider_256",
"ClockDivider_1024"
};
// can't accomodate 2'30'' and above without an external multiplier.
const int multiplierStartIndex = 40;
const u16 partialShutterMultipliers[] = {
2, // "2''5"
// ...
900 // "30'"
};
u16 shutterMultiplers(int index)
{
if(index < multiplierStartIndex)
return 1;
else
return partialShutterMultipliers[index-multiplierStartIndex];
}
| Provided by website-hit-counters.com . |