Flashlight Firmware Repository

I am not very good at running a compiler. My initial problems were caused during project creation, the program in both versions wanted the .c file to be called main.c. I had to remove that file from the project after importing the desired.c file.

Here are the changes that I made, I desired to remove the both of the blinky modes so I could get to the battcheck easier.

// Hidden modes are before the lowest (moon) mode, and should be specified
// in reverse order. So, to go backward from moon to turbo to strobe to
// battcheck, use BATTCHECK,STROBE,TURBO .
#define NUM_HIDDEN 2
#define HIDDENMODES BATTCHECK,TURBO
#define HIDDENMODES_PWM PHASE,PHASE
#define HIDDENMODES_ALT 0,0 // Zeroes, same length as NUM_HIDDEN

#define TURBO 255 // Convenience code for turbo mode
#define BATTCHECK 254 // Convenience code for battery check mode
// Uncomment to enable tactical strobe mode
//#define STROBE 253 // Convenience code for strobe mode
// Uncomment to unable a 2-level stutter beacon instead of a tactical strobe
//#define BIKING_STROBE 252 // Convenience code for biking strobe mode
// comment out to use minimal version instead (smaller)
//#define FULL_BIKING_STROBE

Hey! Also gained some space on the CPU.

Studio 7 output log!!!

——— Build started: Project: BLF-A6_no_blink, Configuration: Debug AVR ———
Build started.
Project “BLF-A6_no_blink.cproj” (default targets):
Target “PreBuildEvent” skipped, due to false condition; (‘$(PreBuildEvent)’!=’‘) was evaluated as (’‘!=’‘).
Target “CoreBuild” in file “C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Compiler.targets” from project “E:\AVRdude\BLF-A6_no_blink\BLF-A6_no_blink\BLF-A6_no_blink.cproj” (target “Build” depends on it):
Task “RunCompilerTask”
Shell Utils Path C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils
C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils\make.exe all
Building file: …/./blf-a6.c
Invoking: AVR/GNU C Compiler : 4.9.2
“C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe” -x c -funsigned-char -funsigned-bitfields -DDEBUG -I”C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.0.68\include” -Os -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=attiny13a -B “C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.0.68\gcc\dev\attiny13a” -c -std=gnu99 -MD -MP -MF “blf-a6.d” -MT”blf-a6.d” -MT”blf-a6.o” -o “blf-a6.o” “…/./blf-a6.c”
Finished building: …/./blf-a6.c
Building target: BLF-A6_no_blink.elf
Invoking: AVR/GNU Linker : 4.9.2
“C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe” -o BLF-A6_no_blink.elf blf-a6.o -Wl,-Map=“BLF-A6_no_blink.map” -Wl,—start-group -Wl,-lm -Wl,—end-group -Wl,—gc-sections -mmcu=attiny13a -B “C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.0.68\gcc\dev\attiny13a”
Finished building target: BLF-A6_no_blink.elf
“C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe” -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures “BLF-A6_no_blink.elf” “BLF-A6_no_blink.hex”
“C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe” -j .eeprom —set-section-flags=.eeprom=alloc,load —change-section-lma .eeprom=0 —no-change-warnings -O ihex “BLF-A6_no_blink.elf” “BLF-A6_no_blink.eep” || exit 0
“C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objdump.exe” -h -S “BLF-A6_no_blink.elf” > “BLF-A6_no_blink.lss”
“C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe” -O srec -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures “BLF-A6_no_blink.elf” “BLF-A6_no_blink.srec”
“C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-size.exe” “BLF-A6_no_blink.elf”
text data bss dec hex filename
920 0 13 933 3a5 BLF-A6_no_blink.elf
Done executing task “RunCompilerTask”.
Using “RunOutputFileVerifyTask” task from assembly “C:\Program Files (x86)\Atmel\Studio\7.0\Extensions\Application\AvrGCC.dll”.
Task “RunOutputFileVerifyTask”
Program Memory Usage : 920 bytes 89.8 % Full
Data Memory Usage : 13 bytes 20.3 % Full
Done executing task “RunOutputFileVerifyTask”.
Done building target “CoreBuild” in project “BLF-A6_no_blink.cproj”.
Target “PostBuildEvent” skipped, due to false condition; (’$(PostBuildEvent)’ != ’‘) was evaluated as (’’ != ’’).
Target “Build” in file “C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Avr.common.targets” from project “E:\AVRdude\BLF-A6_no_blink\BLF-A6_no_blink\BLF-A6_no_blink.cproj” (entry point):
Done building target “Build” in project “BLF-A6_no_blink.cproj”.
Done building project “BLF-A6_no_blink.cproj”.

Build succeeded.
Build: 1 succeeded or up-to-date, 0 failed, 0 skipped

K, cool!! Smile

Here is the code I’ll be referring to, Stock STAR momentary on the left, my code on the right.

It will be used in a dual switch light. As far as I can tell, whenever power is applied to the driver, it should turn on the LED in the “3” mode (max). It does do this when the power is removed while the light is on, but if the power is removed when the light is in the “0” mode (off), it comes back on in the same “0” mode after power is reapplied, instead of defaulting to “3” mode like it should. I’m sure its a quick fix, but I don’t know what it is.

Help?

Not sure if I'd depend on the mode variable initialization like that. Try setting mode_idx to 3 just before the main while loop - then there's no doubt it is set and should be acted on since last_mode_idx is set to 0 - guaranteed it's processed in the main loop.

that makes sense to me in a logical way, but not in a firmware way. I tried just throwing “mode_idx = 3” before the longest loop and it just gave me a bunch of compile errors. What do i need to do?

I think i got it working the way I want by commenting out a lot of the stuff relating to “sleep”. Will that cause me other issues, like with LVP perhaps?

New Diffcheck. (mine on the right)

That sounds weird - sleep mode shouldn't have anything to do with a clean power up... Sounds like the mode_idx set to 3 is not working.

Putting the following statement in a line by itself before the while(1) line should definitely compile ??? I've only been programming in C since 1982 or so Smile Frown.

mode_idx = 3;

You of course were right, I just didn’t know how to read what you were saying H)

I’ve got it in the right place now and it works great, thanks.
……………………….

Next issue:
the way I have the modes ordered, I can cycle through lo-hi-lo-hi without hitting the hidden “medium” that turbo steps down to. However, I think this means that if LVP steps in, things will be messed up.

If I’m in High mode when LVP starts, it will step down to low, then step “down” to medium, then to sleep. Or if I’m in the hidden medium, it will step down directly to sleep.

What can I do to fix this?

At a glance, it looks like it has off, medium, low, high. So, LVP stepping down goes high, low, medium, off. Yes?

You could either modify the logic for LVP… or throw out the idea of using mode_idx at all for step-down and modify PWM levels more directly. Not sure which would be easier. I prefer the second approach, but it’s harder to fit into STAR-based projects.

Yes, looks like you are right. I noticed your mod to the next_mode() function, and the seemingly odd mode ordering. You probably have to have a special prev_mode that's used for LVP only, skipping mode 1, or to make it more flexible, skip a previos mode that has a higher PWM value, but that's a bit more involved. Depends how much code space you have, and how flexible you want it to work.

You are still in the tiny world of the 13A with this driver .

Is there a different way I can order the modes to keep medium hidden but also lvp linear? Like, if I swap the order of low and Medium, can I get it to skip over medium in normal mode order? Like, “when switch is pressed: if mode is low, go to high. If mode is not low, go to low”?

I’m not too worried about jumping to the 25/85 because I like a very simple user experience. Though I did buy a 25 for my 7G3CS because I want the temp monitoring.

Well, lots of options. Like TK said, you could simply hard code LVP. I'd tend to keep the mode table in proper order so LVP works fine, but skip the next to last mode (med mode) in next_mode(). When LVP kicks in, it doesn't limit use of the higher modes, so normal nav still works and it won't be broken.

If you have enough room left, you can do anything you want. The only real limitation is ROM space.

Most of the logic you described seems pretty straightforward too. Just add some extra clauses to detect the mode and step down in different ways, and it should be fine. Or you could perhaps do it in less space by using a mode change table… like each entry would define what “stepping down” means from that mode. Here’s a rough idea of what I mean:

uint8_t modes = {0, 0, 0, 255};
uint8_t altmodes = {0, 255, 30, 255};
uint8_t stepdowns = {0, 2, 0, 1};

void stepdown() {
  mode_idx = stepdowns[mode_idx];
}

I suspect Tom’s suggestion would be simpler though. :slight_smile:

That works. How do I make it skip the next-to-last mode?

Something like this:

if (++mode_idx == (sizeof(modes) - 2))

++mode_idx;

if (mode_idx >= sizeof(modes))

...

...

Ok - you'd be adding the first 2 lines, and modding the 3rd line to remove the ++. This is all in the function: next_mode().

Hope I made this clear enough. Basically you detect if the mode is incrementing to the 2nd highest mode. If so, increment the mode index again.

I think I have everything working now. I haven’t actually tested LVP yet, but I don’t know why it wouldn’t work as the mode order is now back to “normal”.

Would one of you mind looking over it to make sure there isn’t some hidden screw-up that will cause me grief later? thanks

once again, mine is on the right, stock STAR is the left.
Diff check

edit: JK, now I’m back to having the problem that when power is cycled when in mode “0” it doesn’t come on in mode “3”. :frowning:
plot twist: So if I hold the button for 2.5 seconds it enters mode “0” (off). If I then remove power for <5 seconds, when power is reapplied it is still in mode “0” (no bueno). However, if I remove the power for >5 seconds before reapplying, it comes on in mode “3” as it should. Any ideas here?

There's something that's keeping power goin for 5 secs - no other explanation I can think of. Cap? Something?

Oops, forgot to update here.

That issue was on my “power supply.” I decided it wasn’t a big deal, so I installed it in the light anyways. Miracle of miracles, once in the light that weird behavior went away.

U mean a bench PS? Ohhh - if so, would explain the 5 secs shutdown... My bench PS is super slow on shutting down.

FWIW, I did some tests a while ago for the mem-decay method of detecting short presses. If I drain the OTC, it seems to take about 0.5s for the memory to decay. If I leave the OTC fully charged, it seems to take about 4s for memory to decay.

Just a thought. I don’t even know if you’re using that method.