STAR Firmware by JonnyC - Source Code and Explanation

Well, it is possible, by changing to phase-correct instead of fast-PWM, but the issue isn't anything to worry about. It doesn't do anything at all except keep the LEDs dimly on if you hold the button down after backing up from the 1st mode to off. The MCU goes to sleep as soon as you release the button, that's why the LEDs fully turn off then. Some earlier firmwares used a different sleep strategy, and if they used fast-PWM the LEDs would never fully turn off... but this FW is not like that, as you yourself pointed out - the LEDs do turn fully off.

If you would rather change it to phase-correct and end up with a light that squeals like a stuck pig in the upper-middle modes, all to get rid of something that only happens when you keep holding the switch button after you've told the light to turn off, well....

I decided to try what you have called the phase correct ( 0*21 thing) to see what would happen. The low level light when the button is pressed is no longer there, and yes I do get a slight buzz, but only audible if I’m in a really quiet room and ear right near the torch. That’s not a problem for me, unless it is some way damaging the driver.

Is it genuinely loud for you went you use the phase correct? Maybe im lucky mine is very quiet. Or you just don’t like the very slight buzz?

The only time I get bad whine with the phase correct is when I use it with an inductor. Otherwise there are only a few modes that I can hear and they aren't very loud. With the inductor and flyback diode the noise is pretty bad IMO.

I removed the star-soldering logic to make room for more modes and features… here is an example of how that turned out:
http://bazaar.launchpad.net/~toykeeper/flashlight-firmware/trunk/view/head:/ToyKeeper/s7/s7.c

I run this on my EDC, and it provides five nice constant-output modes plus a bunch of interesting blinkies… with no need to cycle through the blinkies when not desired.

Thanks, that explains a lot. I was having issues with a custom firmware where the LEDs wouldn’t run off all the way, and now I know why. :slight_smile:

(was trying to implement a ZL-like UI, but so far it looks like it won’t fit into just 1024 bytes)

ok thanks toykeeper! i only have one strobe mode. i prefer off-time memory and that takes up space in the code. its hard to go back to on-time memory. i did figure out how to remove the stars to save a little room. i was getting errors before, but i didnt know that #ifdef modes had to be under an inline void or where i put them is after int main (void).

Any line which starts with ‘#’ is a precompiler directive. All that stuff gets evaluated before even sending the code to the regular compiler. So, if you have anything like ‘#ifdef foo … #endif’ and ‘foo’ isn’t defined, the entire section of code will get deleted before it tries to compile anything. It doesn’t care if you put them near an inline void or after main or anywhere; all that stuff is a completely different language.

Basically, the #if and #ifdef stuff is there to give us an easier way to put several different versions of the same code into the same file, or to change things just before compiling. It’s not part of the actual program logic though. It simply trims out lines or search-and-replaces keywords before attempting to compile.

isnt #ifdef referring to #define?

well when i deleted this in star_off_time it had errors and wouldnt compile,

inline void check_stars() {
// Load up the modes based on stars
// Always load up the modes array in order of lowest to highest mode
// 0 being low for soldered, 1 for pulled-up for not soldered
// Moon
#ifdef MODE_MOON
if ((PINB & (1 << STAR2_PIN)) == 0) {
modes[mode_cnt++] = MODE_MOON;
}
#endif

but when i put it here it compiled fine,

int main(void)
{
// All ports default to input, but turn pull-up resistors on for the stars (not the ADC input! Made that mistake already)
PORTB = (1 << STAR2_PIN) | (1 << STAR3_PIN);

//mode order
#ifdef MODE_MOON
modes[mode_cnt++] = MODE_MOON;
#endif
#ifdef MODE_LOW
modes[mode_cnt++] = MODE_LOW;
#endif
#ifdef MODE_MED
modes[mode_cnt++] = MODE_MED;
#endif
#ifdef MODE_HIGH
modes[mode_cnt++] = MODE_HIGH;
#endif
#ifdef MODE_TURBO
modes[mode_cnt++] = MODE_TURBO;
#endif
#ifdef MODE_STROBE
modes[mode_cnt++] = MODE_STROBE;
#endif

i think this "inline void check_stars()" puts "#ifdef MODES_" after "check_stars()" under int main(void).

When testing the drivers out in the open it can be not that bad (since most of the noise isn't coming from the driver itself), but once in a light the springs, switch, and even the battery vibrating against the inside of the tube can get annoyingly loud. It's certainly not anything I'm willing to live with in response to something that only happens when I intentionally hold the switch after it should have been released.

Just curious, but why is the LEDs-on-when-button-held thing bothering you? The light works exactly as intended. If the LEDs didn't shut off after you released the switch, then sure, that something that's not acceptable, the light isn't working properly. But this? It's a non-issue. It doesn't cause anything else at all to happen ever, it doesn't cause higher parasitic drain, since the MCU sleeps as it should as soon as you release the switch.

I’m not entirely sure what you mean, but if I saw the errors I could probably explain what caused them.

If you removed the entire chunk of code you pasted, I can see why it wouldn’t compile. The snippet included the beginning but not the end of a function, leaving the code in a malformed state.

On a different note, JonnyC never responded about the code repo. I suppose perhaps I should relocate to github so at least I’m using the same infrastructure and can more easily merge changes. Git may not be as clean about how it keeps history, but it’s important for everyone to be using the same tools.

i think what caused the errors is #ifdef MODES_ has to be under int main(void) for the code to run in the correct order.

if i would have put #ifdef MODES_ under int main(void) after this code for off-time memory it will not compile,

// Start up ADC for capacitor pin
DIDR0 |= (1 << CAP_DIDR); // disable digital input on ADC pin to reduce power consumption
ADMUX = (1 << REFS0) | (1 << ADLAR) | CAP_CHANNEL; // 1.1v reference, left-adjust, ADC3/PB3
ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL; // enable, start, prescale

// Wait for completion
while (ADCSRA & (1 << ADSC));
// Start again as datasheet says first result is unreliable
ADCSRA |= (1 << ADSC);
// Wait for completion
while (ADCSRA & (1 << ADSC));
if (ADCH > CAP_THRESHOLD) {
// Indicates they did a short press, go to the next mode
next_mode(); // Will handle wrap arounds
store_mode_idx(mode_idx);
} else {
// Didn't have a short press, keep the same mode
#ifndef MEMORY
// Reset to the first mode
mode_idx = ((mode_dir == 1) ? 0 : (mode_cnt - 1));
store_mode_idx(mode_idx);
#endif
}

or at least thats when i quit getting errors.

Sorry. I ended up just creating a Github repository mostly for my own sake (so I could keep track of my different versions, start branches for the dual-PWM feature so people could try them, etc.). Feel free to do whatever you want with the STAR code. I don't plan on keeping track of all of the different variations out there (NLITE, etc.). I don't think it's that necessary to store all possible programs in one repository as long as we link to them from somewhere. Maybe we could create a new thread on here that lists them all and what they do, and keep the first post updated whenever something new comes out. I'm not up to the task though ;)

im not a coder, i am just trying to learn from trial and error, but doesnt { and } begin and end a function? i removed more than i posted.

It doesn’t overly bother me, but if I had a choice I would prefer it react how it does on low pwm mode. As I don’t understand what the buzzing is about, and if it is damaging anything, I changed back to high pwm and will be very happy with how it performs.

So you removed the function. Did you remove the call to that function then?