Flashlight Firmware Repository

In detail, this is what changed:

https://bazaar.launchpad.net/~toykeeper/flashlight-firmware/fsm/changes

I have been looking at the Anduril firmware for a project light I am working on. Got it to compile now I am trying to understand it so I can design the driver.

The big hangup I am having right now is the LVP. The drivers that do not use a voltage divider still seem to use a pin for ADC measurements in the firmware. Where / What is the setting to switch between a voltage divider and internal voltage sensing?

Setting: ADMUX_VCC in tk-attiny.h, with a mix of the hardware-definitions (hwdef-BLF_GT.h vs hwdef-Emisar_D4.h, #define USE_VOLTAGE_DIVIDER)

Where it's done: fsm-adc.c

In fsm-adc.c, it switches between reading the temperature and VCC values.

Thanks, keep in mind I know just enough about C code to get my self in trouble and fully admit it.

So best I can understand, if the” #define VOLTAGE_PIN” is set to PB2 (maybe it ignores the pin completely when using the internal ref?) and “#define USE_VOLTAGE_DIVIDER” is not set, then it defaults to the internal voltage reference and there is nothing else I need to do.

If “#define USE_VOLTAGE_DIVIDER” is set then it uses an external voltage divider?

So basically adding or removing the “#define USE_VOLTAGE_DIVIDER” is all I need to do to switch between these options?

What about pin 7? What does it need to be connected to if using the internal voltage? Can it be used as an indicator LED output? Can I set the voltage sensing (internal or external) to another pin?

That seems to be the case, if you set USE_VOLTAGE_DIVIDER, it uses ADMUX_VOLTAGE_DIVIDER for measurements, otherwise it uses ADMUX_VCC

It also sets up the pins (DIR0) differently if it is used.

You're free to use pin 7 for anything else you desire if you use internal VCC measurement.

Yes you can use it as an indicator LED, please see my Texas Avenger 21mm Skilhunt H03 config for reference.

This config may have a problem with space as I have some other tweaks in my fork.

Removing #define TICK_DURING_STANDBY frees up enough space so it fits onto the 8KB of flash.

hwdef-H03-TA.h

/* TA 21mm H03 driver layout
 * ----
 * Reset   -|1 8|- VCC
 * eswitch -|2 7|- indicator led
 * FET     -|3 6|- 7x7135
 * GND     -|4 5|- 1x7135
 * ----
 */

#define PWM_CHANNELS 3

#define SWITCH_PIN PB3 // pin 2
#define SWITCH_PCINT PCINT3 // pin 2 pin change interrupt

#define PWM1_PIN PB0 // pin 5, 1x7135 PWM
#define PWM1_LVL OCR0A // OCR0A is the output compare register for PB0
#define PWM2_PIN PB1 // pin 6, 7x7135 PWM
#define PWM2_LVL OCR0B // OCR0B is the output compare register for PB1
#define PWM3_PIN PB4 // pin 3, FET PWM
#define PWM3_LVL OCR1B // OCR1B is the output compare register for PB4

#define AUXLED_PIN PB2 // pin 7, indicator led

#define ADC_PRSCL 0x06 // clk/64
// average drop across diode on this hardware
#define VOLTAGE_FUDGE_FACTOR 5 // add 0.25V

#define TEMP_CHANNEL 0b00001111

#define FAST 0xA3 // fast PWM both channels
#define PHASE 0xA1 // phase-correct PWM both channels

cfg-h03-ta.h

// TA 21mm H03 config options for Anduril

// the button lights up
#define USE_INDICATOR_LED
// the aux LEDs are behind the main LEDs
#ifdef USE_INDICATOR_LED_WHILE_RAMPING
#undef USE_INDICATOR_LED_WHILE_RAMPING
#endif
// enable blinking indicator LED while off
#define TICK_DURING_STANDBY

#ifdef RAMP_LENGTH
#undef RAMP_LENGTH
#endif

// …/…/bin/level_calc.py 1 65 7135 1 0.8 150
// … mixed with this:
// …/…/…/bin/level_calc.py 3 150 7135 1 0.33 150 7135 1 1 850 FET 1 10 1500
#define RAMP_LENGTH 150
#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,7,8,9,10,12,13,14,15,17,19,20,22,24,26,29,31,34,36,39,42,45,48,51,55,59,62,66,70,75,79,84,89,93,99,104,110,115,121,127,134,140,147,154,161,168,176,184,192,200,209,217,226,236,245,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0
#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,4,6,8,10,13,15,17,19,22,24,26,29,31,34,37,39,42,45,48,51,54,57,60,64,67,70,74,77,81,85,88,92,96,100,104,108,112,116,121,125,130,134,139,143,148,153,158,163,168,173,179,184,189,195,201,206,212,218,224,230,236,243,249,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0
#define PWM3_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,19,31,43,55,67,79,91,104,117,130,143,157,170,184,198,212,226,240,255
#define MAX_1x7135 65
#define MAX_Nx7135 130
#define HALFSPEED_LEVEL 14
#define QUARTERSPEED_LEVEL 5

// stop panicking at about 3A or ~1100 lm, this light is a hotrod
#define THERM_FASTER_LEVEL MAX_Nx7135
// optional, makes initial turbo step-down faster so first peak isn't as hot
#define THERM_HARD_TURBO_DROP

Internal? No. Thats - as the name implies - internal. If you want to set it to another external pin, you would need to update the registers used in the hwdef-*.h file:

#define USE_VOLTAGE_DIVIDER // use a voltage divider on pin 7, not VCC
#define VOLTAGE_PIN PB2 // pin 7, voltage ADC
#define VOLTAGE_CHANNEL 0x01 // MUX 01 corresponds with PB2
// 1.1V reference, left-adjust, ADC1/PB2
//#define ADMUX_VOLTAGE_DIVIDER ((1 << V_REF) | (1 << ADLAR) | VOLTAGE_CHANNEL)
// 1.1V reference, no left-adjust, ADC1/PB2
#define ADMUX_VOLTAGE_DIVIDER ((1 << V_REF) | VOLTAGE_CHANNEL)
#define VOLTAGE_ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2
#define ADC_PRSCL 0x06 // clk/64

ok, I think I am getting it now. Seeing a defined pin for the internal reference really threw me for a loop.

So if it is using the internal reference then it is also ignoring the pin defined for the voltage divider and I am free to use it for something else.

I wounder why the pin 7 is defined at all for those drivers? Seems like it would be commented out completely?

Thanks for taking the time to explain it.

My best guess: copy&paste as you can see the comment in hwdef-Emisar_D4.h

// (FIXME: remove?  not used?)
#define VOLTAGE_PIN PB2     // pin 7, voltage ADC

Thanks for answering all that over the past few posts. :slight_smile:

The API for voltage measurement is, um, not ideal. It’s not really designed so much as just kludged together over time. I’ll probably want to rewrite it when I add support for a new MCU architecture, but I don’t know when that will be. Writing all these abstraction layers takes a while, and the hardware abstraction parts aren’t anywhere near as mature as the UI abstraction parts.

So for the moment, it’s a bit of a mess.

Great, at least I can switch pin 7 to AUXled duty, using pin 3 would of been more difficult. So this is all I should have to do to setup the drive with FET + 1x 7135 + AUX led.

Having PB2 defined twice will not matter correct? Or should I comment out the ADC section entirely?

Sorry, this driver is kind of a last minute addition to a light Neal asked me for that is already in the works and I will not have time for a second prototype I am sure, so I need to get the hardware right the first time and preferably the firmware as well.

As I start to learn my way around Anduril I can see the advantages it brings to the table, although I am sure I will have more questions before I am comfortable with it. Took me 6 months to get comfortable with Bistro and then Narsil but I am getting better each time.

Thanks again for the help.

EDIT: Are the fuses the same as Bistro?

This is what I use now:

lfuse:w:0xd2:m
hfuse:w:0xde:m
efuse:w:0xff:m

Referring to PB2 from more than one place shouldn’t cause issues, as long as only one part tries to use it. The voltage pin thing isn’t used unless it also has the USE_VOLTAGE_DIVIDER thing enabled.

The recommended fuse values are always in bin/flash-85.sh.

There is some debate about whether BOD should be enabled, but it doesn’t appear to matter much in practice.

For what kind of light does Neal need a last-minute Anduril driver? Should I trust that people will follow the license requirements this time?

I was looking at the flash scripts and noticed that the fuses are different for the tiny25 and tiny85, I used to use the same settings for both, has that changed?

Tiny85 -
lfuse:w:0xe2:m
hfuse:w:0xdf:m
efuse:w:0xff:m

Tiny25 -
lfuse:w:0xd2:m
hfuse:w:0xdf:m
efuse:w:0xff:m

I am not sure that I am supposed to say anything about the light at this point, not sure what the status on it is, I was not really involved with it until a week ago and then only as a “hey, we need a better driver, can you make one? Oh and I would like to use Anduril” type thing lol.

I am not even sure who is making it come to think of it. Heck, I am not even sure about what the light is, I only know it needs a 17mm driver and to support a fair amount of power.

On my end, I always keep all the source files, and credit those needed on the silk screen (unless they remove it, like one manufacture did). So I try to do everything I can to maintain the license, just not always in the most timely fashion.

If you ever have questions or issues with the driver or firmware for a light I worked on, please let me know and I will get you whatever you need. It might be “messy” but I am happy to send it your way. Although I am getting better at keeping things a little more organized as I work now.

The low fuse value of D2 vs E2 selects a startup time of 64 ms or 4 ms. This is how long the MCU waits for power to stabilize before starting to run code. In general it doesn’t matter, as either one should be enough. But it used 4 ms on tiny25 since those are mostly clicky-switch lights where a fast response is important… and 64 ms on tiny85 since those are mostly e-switch lights where boot-up usually means the user is screwing the parts together.

Anyway, the license doesn’t care about whether someone’s name is inscribed onto the PCB. It’s about making sure that anyone who distributes the product also makes the source code available under the same license. Usually this means putting a note in the manual and/or product page stating that the product uses free software, with a link pointing to the code. Putting a conspicuous notice somewhere with the copyright and licensing info is mostly just a means to an end. Attribution isn’t the goal, but because of how copyright law works it’s kind of a necessary prerequisite.

I finally merged FSM into trunk again today. It included several bug fixes and other updates since the last merge.

  • Added support for Fireflies lights.
  • Tweaked thermal settings for a few lights.
  • Fixed a bug with one very specific click sequence causing a MCU hang.
  • Fixed a bug where changing the ramp style could sometimes jump to the wrong brightness.
  • Added a moon timing hint on hold-from-off.
  • Fixed a timing inconsistency on hold-from-off; stepped ramp took too long to start ramping up.
  • Added manuals for RampingIOS V2 and V3.
  • Added a ramp shape parameter to level_calc.py.
  • Added initial support for a second set of aux LEDs, but it simply copies the behavior of the first set.
  • Fixed a bug where thermal regulation could go up from the requested level after double-click-from-off.

The only UI change people would likely notice from this update is the moon timing hint.

What firmware would you suggest to use with a 7135 driver and a momentary switch (SRK style light)? At the moment I have Attiny13A with STAR firmware. Does that kind of driver work with Attiny25/85 and Crescendo, Bistro or NarsilM?

Bistro and Crescendo use a switch which disconnects power, not an electronic switch like the SRK has. So those aren’t really options.

The attiny13 doesn’t have much capacity in ROM, so it can’t fit Narsil or Anduril. However, if you put an attiny85 on instead, it should work. Those can usually fit onto the same pads, but you might have to bend the legs under the chip to make it fit.

There are some other e-switch firmwares though, and some can run on attiny13. For example, the Ferrero Rocher set has three interfaces to choose from. They just don’t have a lot of features.

So if I change the Attiny13 with an Attiny85 and NarsilM it should work? I was not sure if NarsilM is suitable for a 7135 driver. That would be great because I really like the ramping and the different features on my Emisar D4.

Depending on the details of the driver, it may or may not work. There are a lot of different circuits which can be called “a 7135 driver”.

It is the 46mm SRK 32x 7135 driver from MTN Electronics. There is no FET but only 7135 transistors. Maybe I will try it with Attiny85. I should find out quickly if it works or not when turning on the flashlight.

Oh, I have one of those. I ran Ferrero_Rocher/Ramping_UI_table on it.

It was okay, but the ramp resolution at the bottom was very coarse, and it had no extra features except battcheck. Giving it an attiny85 would give it more features, but would not improve the ramp resolution. Also, you’ll probably have to compile a custom version of the code to make it work, because I don’t think there are existing recipes for any single-channel drivers.

It may also be desirable to remove the voltage divider resistors, to reduce standby current, after getting everything else working. The tiny85 code can get that info from a different pin, so the divider isn’t needed any more.

Maybe the Ferrero_Rocher/Ramping_UI_table would do for me. I rarely use the special modes and the ramping sounds good. So I can just reprogram the soldered Attiny13 and do not need to change it. Also it would be too much for my limited coding experience to compile custom codes. Many thanks for all your useful advice and flashlight firmware!