Flashlight Firmware Repository

I know I invented this (or maybe re-invented? or maybe it's a little different than what you show). gcharts version and mine are from the same discussion. yeah, overload doesn't mean avoid the checks. So we set all four bytes to a vlue of interest, usually the fast press value. If all four are equal it's a short press and the value is valid. I'd just use a magic value to indicate that it's a short press but with a next mode lockout.

Hmm, ok, problem is I only have increment and clear functions presently. Need to set all 4 values now. So that's and ldi and 4 sts, so another 12 bytes. Ok.

Actually brings to mind another issue. The compiler doesn't guarantee to save to RAM every time a value is updated, or even ever. It seems care has to be taken to watch out for optimization, in case of either completely optimizing out, or at least just doing everything in registers without ever writing back to RAM. Of course when it works it works. Maybe it's safer long term to make these noinit and volatile?

Latest HD release has the bump-up done this way.

For OTC:

Fast_presses is set to a magic value on turbo timeout.

On restart If cap is high, it's a short press, fast_presses is assumed valid,

If fast_presses==magic_value, don't increase the mode.

...

If cap is med/low, it's a med/long press, don't care about fast_presses, we're leaving turbo.

For not OTC:

All N_SAFE_PRESSES number fast press bytes are set to the magic value:

If all N agree on startup it's a short press...

rest is the same.

Both the set and check are functions that are macro defined depending if fast_presses is used.

Right now safe_presses just has to be configured manually or not correctly for the build. Update for next micro release will automatically disable safe_presses if OTC or OTSM are used, since it's not needed then. Just forgot to include that.

The safe_presses functions were already there, so wasn't much more work to make this turbo bump up work with it.

Is there any downside when not using the Watchdog Timer ( WDT )?

I’m looking at BLF-A6 and biscotti and neither Turbo nor LowVoltageProtection ( LVP ) use the WDT as older firmware had done.

That saves many bytes, but what about sleep mode idle or energy saving? As the Attiny seems to stay awake and continuing the ‘while’ loop, does it use much power?
Any other disadvantage for LVP or Turbo mode?

Thanks a lot

HQ, I might not understand details of crescendo enough to understand some context I'm missing here.

I can answer a lot for bistro though, and what I've done to it. Classic Bistro doesn't use any timer or idle state for sleep modes. Well it does have waits that are done just by a tight do-nothing loop at full mcu power, so that's the cpu clock timer, but a not a "timer".

I've measured that at about 4mA current draw. The ADC adds about 0.15mA (150uA) so not much. I added idle sleeps, using the clock timer. that reduced it to about 2.1mA, which was important in the context of OTSM.

I also added power off sleep powered by capacitors, using the watchdog timer. This is for fully powered off clicks though, to time the clicks. You can't go to deep sleep while the light is on because PWM won't work.

The watchdog isn't that useful when the light is on because the fastest it will go is 16ms, and to program strobes you need faster than that anyway. So if you want a sleep mode for standard loops, you're going to need one that uses idle sleeps and the clock anyway, and at that point you've already got that, so why use the watchdog?

This idle sleep does increase moon mode battery life significantly (I'd guess about 50 to 70% for 1lumen, could be more if really designing just for that), but that's not why I added it. I added it because it takes 4ms to detect power off and that eats up a bunch of my cap power before I can get the mcu to full sleep, so I need full power to also be as low as possible.

Now the full sleeps that are watchdog timed are down around 8uA, but that requires BODS to get that low (and the right chips), otherwise you'll be up around 30uAs. But again, no PWM during those.

If you're intereste, it's here:

https://budgetlightforum.com/t/-/44344

The idle sleep timer is setup in fr-delay.h.

Can someone help me with latest biscotti?

I would like to flash it but don’t understand all that code.

I would like small change.
On mode 1 have 0.1%, 1, 10, 35, 100, battcheck (no strobe and biking) if possible.

Can someone give me .hex file so I can just flash it without much trouble?

To change that, replace this…

PROGMEM const uint8_t modegroups[] = {
     1,  2,  3,  5,  7,  POLICE_STROBE, BIKING_STROBE, BATTCHECK,

… with this:

PROGMEM const uint8_t modegroups[] = {
     1,  2,  3,  5,  7,  BATTCHECK, 0, 0,

However, there are some other things which depend on the specific driver you’re using. I can’t provide a universal .hex file which works on all drivers. Specifically, the voltage calibration and moon level are pretty sensitive to different hardware. What driver are you using?

Ok, here is a quick & dirty compile with that change. Double check the LVP/battcheck, though. It can vary from driver to driver.

EDIT: oops, TK beat me to the important stuff. What she said :wink:

I’m using red “convoy” branded driver from Simon with 8x7135.
Sorry I didn’t mention it.

Side note about flashing firmware on that driver: incase you haven’t heard about the need to cut the grounding trace on pin5, check out this page over on the flashing guide

I have seen it and already did.

I’m good with hardware part, but code got me lost :blush:

I try to flash driver but got error and not working driver as result. :cry:

Also tryed to flash original fw I saved from driver but same error.

Error

What I flash

What I read

Thanks Flintrock for this answer that helped me at several points. Although I’m looking for 13A firmware. Bistro and your HD is way above my head. I looked at HD briefly, too much code I don’t yet understand and it takes me way too long to google every unknown part.

I just compiled (all with -Os) my old fashioned, ‘Star’-based firmware with LVP to 950 bytes. Then I deleted the flash before stepdown and got 826 bytes. Wow. That alone eats a lot of space.
Then I changed the rest of the LVP part to the code from biscotti (not WDT based) and compiled to 722 bytes.

Now I understand how TK could cram so much into the 13A…

But as I understand that Sleep-Mode-Idle and WDT really saves some mA, and I don’t need strobes, I will try to keep WDT unless all I want to add exceeds 1k.

Hmmm, you firmware people really have been busy in the last 2 years…
Thanks for sharing, to all of you.

Sure, yeah WTD should be fine for idle if you don't need strobes. For sleep mode idle you don't need to see all that code, just the fr-delay.h, but I doubt you need to see it. You know how to use WTD and how to enter sleep.

Bistro HD actually has attiny13 support. In fact it has a biscotti-HD configuration already built in the Makefile, (and somewhat customizable from its config file) that comes in a few bytes smaller than original biscotti with a couple of added features. I don't recall if I have the sleep mode enabled. It's the OTSM_powersave option, which actually works even if OTSM is not used (I should change the name of that control).

It does seem that I've put a warning and an undefine for this option in attiny13. But now I can't remember or see any good reason why. I just uncommented that and compiled it with that option and it compiled fine, so it must not be using anything undefined for attiny13. maybe I just did it to save bytes. Hmm.. It does bring the biscotti build up to 1032 bytes, but if nothing else just removing the added turbo-timeout feature will get it back down. I really can't see why I disabled that option now. Maybe I'll un-disable it. hmm..

The bistro HD code does start to look a bit overwelming. I tried to avoid code re-organization becuase there was a tradition of single file compilation without even function prototypes. This makes it easier for some simple compiling methods and was fine for bistro, but it starts to get close to its limit now, and is bending the rules a bit.

Anyway, one thing I did add is the makefile produces preprocessor output for all builds, stripped of comments. Other than some ugly MACRO expansions of things like PORTB and pgm_read_bytes(), these put the code into the lean and clean form after all preprocessor configurations are factored in. Maybe I'll start including those in the distribution.

So my single-cell battery charger had been way under charging recently and I hadn't noticed or cared much. But that explains this light not getting hot. (I thought I had others I'd been using before that got hotter). Now it runs at 3.5A (on still slightly less than full Pannies) and the thermal protection kicks in. But it is very on and off. It hits the limit and marches way down to 1st mode... cools off a while, and marches straight back up, repeats. Probably related to poor thermal path.

The thing is though really nailing feedback problems like this in a general way, is very very difficult. You can do it with just a proportional gain (probably what Dr.Jones does), but there's probably no one gain that will work well for every light. You'd probably need to work out a response time and extrapolate curves to predicted temperatures, correct, re-measure, extrapolate the correction... Not easy, especially for an attiny.

I wonder though if just having it somewhere inbetween bistro and BLFA6 would be good.

Update: ok, so the problem is that the goal isn't even clearly defined. There are really two very separate uses. One is someone wants to be able to see something with the most light possible once in awhile. That's true turbo mode. Two is someone wants to get the maximum sustainable power out of the light, possibly in changing conditions (this is biking mode really) For option one, finding the stable power level isn't even useful, going to that level prevents ever returning to turbo because you keep the light maximally hot. And dropping down way low, and automatically returning to turbo also isn't useful. You're not going to be able to know when the user needs turbo again anyway, and bouncing up and down is silly. So timeout, or temp-out and bump up makes tons of sense for option 1. Dynamic regulation doesn't make sense for option 1. For option 2 you never need to even reach turbo. The best system would analyze the heat curve and zoom in on the sustainable target without ever overshooting it in the first place. You could overshoot a little and then settle in, but I don't see much point. These might even be ideally different modes, although every mode should probably have the temp regulation applied, for safety.

Option 1 can be modified so it "times"-out on temperature instead of time. That would be nice, but it's still then just a single big step down and wait for the user to bump it up.

The further problem though is that option 2 is very very difficult to actually achieve in a general way for every light you might flash the firmware to. Gain feedback probably needs to be tuned, or needs to be very smart. So is it even sensible to have any mode that dynamically regulates on a generic firmware? Maybe it makes sense just to have a defined COOLDOWN mode and any time any mode maxes out on temperature it resets to there, with ability for bump up (but this time with timeout?). That adds safety to all mode levels, and provides option1 functionality, but doesn't attempt to provide option 2, and certainly doesn't attempt to mix them, which I think just doesn't make sense really.

Ok, nuff talking stuff done.

attiny13 idle

Regarding powersaving in attiny13 I had disabled the attiny idle sleep aparently because it didn't compile on the 13 and it just got it going, but the reason was that Atmel decided to do entertaining things like call the timer 0 interrupt TIM0_OVF_vect on attin13 and TIMER0_OFV_vect on attiny25, just to mess with us. So some macro defines sorted it. So biscotti-HD for attiny13 can now have pwersaving and actually it does fit (confused myself earlier). I consider that one of several customizable bonus features though.

Thermal turbo boost

Regarding thermal control. I threw together a quick BLFA6 like turbo except it applies to all modes and it jumps down based on temperature not time. Otherwise it's like BLFA6 though, not like bistro. When too hot, it jumps down to a predefined mode (default RAMP_SIZE/2 for now). A fast tap bumps it back up. I thought it might be nice to switch to timeout control after the bump-up but that probably adds more code, and actually I like it this way. You still get 4 seconds minimum because that's how long it spends verify the overtemp, but then it will pull you back down again if it's still too hot. 4s is enough to see something in a pinch. I could somehow pad it with initial time to increase minimum time without further increasing the first overheat delay. I really like this setup. The auto multi-step down auto multi-step up alternative just starts doing its own dance that doesn't really help me use the light. This just protects the light, and then puts me back in control. Oh and it came in 10 bytes lighter.

I'd consider a true temp regulated mode as a different thing and a more difficult task, and something to be added in addition to this. I might play with it. I think you can roughly predict the final temp as linear combination of the last two readings. It doesn't need to be a good prediction so long as it converges correctly. The tough part is figuring out the correction gain. This is predictive though not reactive, and so hopefully wont oscillate, but it still probably can oscillate in some conditions. Anything mathish like this though tends to take a bunch of bytes.

Hey FR, I’d love to take a peek at that attiny13a interrupt code. Do you have it posted anywhere?

It's in HD:

https://budgetlightforum.com/t/-/44344

Nothing actually changed in the code, just some of ATMEL's register macros. As I recall TIMER0_OVF_vect had to change to TIM0_OVF_vect and TIMSK and to change to TIMSK0. there might ahve been another one but it will be obviouus when you try it.

So I change them to _TIMER0_OVF_VECT_ and _TIMSK_ and in fr-tk-attiny.h

add

#if ATTINY == 13

#define _TIMSK_ TIMSK0

...

you get the point.

I'll post this new version up soon though, but that's all I change, oh and removing the override on that on option.

Oh yeah, the relevant part of the code is in fr-delay.h. You need the interrupt there, and the initialization is mostly done in the delay function, although as I recall actually configuring and enabling timer0 is done in init_mcu in bistro.c You can ignore the PWM4 stuff. Basically if PWM4 is engaged I have another interrupt waking at known intervals anyway, so I use that instead and don't setup another one, but you can just ignore that.