STAR Firmware by JonnyC - Source Code and Explanation

I just tried the offtime memory. Awesome stuff. not tested it in a light but on a power supply it works perfect.
I used a 10uF cap and a CAP_TRESHHOLD value of 200.
The batteryprotection kicked in abit to low for my feeling so I bumped the criticallevel a bit.
I like it very much that you have added a level were the power is totally down. THUMBS UP!
I just added a line to disable the ADC, you already have a procedure in the code. This helps to reduce the current a lot. You even use the idle mode as a standard.
No memory works like a champ too. Fantastic.

I have a question because there is something which confuses me
What does this line: while (!low_voltage(ADC_CRIT));
its in the main routine.

It (busy)loops until voltage is critically low.

I would put the semicolon to separate line to improve readability. :)

Yup, _the_ has it right. Glad it's working for you!

I posted up a dual switch program on my site (for rear clicky + side switch), but I haven't fully tested it out yet and RMM hasn't given it his normal runthrough either. Once it's tested I will post up and we can see what additions can be added if needed.

I flashed the momentary firmware last night on a nanjg, it works quite well.
Never played with the turbo timer but thought for a small light it might be usefull.
I can read the code quite well and it is a simple but very nice code.
I changed it a bit so that it slowly dims down to previous mode and not so harsh and I also dim down on the two highest modes because the half power mode is on 3rd place. But because I thought that dimming is just for pussies I dim down after 5minutes but this is to long to prevent finger burning….5minutes on 4.4A and again 5 with 3A are to much…maybe I will shorten that a bit after a few days of playing with it.

I used a sipik ck12 clone and a 4.4A nanjg.

I've started work on putting an ATtiny13A on a LD29 driver board. Thread link: here is the LD-29 MCU pinout (eg how to put your ATtiny13A in there...). An adapter PCB is pictured in post #27 which will allow the ATtiny to pickup the right pins for power, ground, ADC inputs, etc.

I've also started work on the changes to get STAR_offtime working with this, see post #34. As I posted the code I noticed one glaring mistake (STAR2_PIN should have been removed), but I welcome any review to find additional mistakes.

FWIW, I’ve started a firmware repository and I added a new STAR flavor designed for use as a bike tail light.

The repository currently only contains STAR and a couple derivatives, but I’ll be adding anything and everything I can get permission to share.

The biking tail light code will go into a little 1x16340 light with red XP-E2 as soon as I get the host. It has the following modes: moon, low, med, high, moon-low flasher, low-med flasher, med-high flasher, and heartbeat. It’s my first attiny firmware and I only spent a couple hours on it so far, so it’s a work in progress. However, it does at least work if anyone is interested.

The firmware repository is on Launchpad:
Here’s the link if you’d like to browse the code online.

The tail light .hex file is also pre-built for easy flashing: here.

Nice thanks!!

BTW, I just wanted to thank everyone who has contributed to the STAR firmware.

When I was little, I learned how to read from a programming manual. I learned about variables and syntax errors before I ever heard of Dick & Jane or an Etch-A-Sketch. As long as I can remember, I’ve been putting code into a computer to make it do what I want, and my current computers have their screens filled up almost entirely with stuff I created. It’s just how I do things.

But with flashlights, something was always missing. I’ve really enjoyed them, and modding lights made it even more fun, but there were always little things I still wanted to change…

Until the past couple days, that is.

Today I took apart one of my lights, wrote some new firmware for it, flashed it, tweaked it, put it all back together, and now it’s finally doing what I wanted all along — namely, whatever I told it to do. Its behavior may have been just thrown together quickly based on what I wanted from it today, but that’s okay. It feels right. That’s how things are supposed to be. It’s running custom code which didn’t exist this morning, a crystalized snapshot of my ideas, dumped out of my brain so I could get rid of them and make room for new ideas.

Is it “finished”? Probably not. I’ll probably reflash it a few dozen more times in the foreseeable future. But that’s okay too, code is fluid and changes with circumstance.

As for STAR, I’m thankful because other people already did all the hard parts. It’s a great basis for derivative projects. I didn’t have to spend all week referring to the encyclopedic attiny13a manual to figure out basic things like using the watchdog timer to implement short-cycle memory, or painstakingly measure the values for low-voltage detection. I got to do the fun parts instead, designing modes and watching them in action just moments later. So thank you! I’m having a great time and making all sorts of terrible blinky things.

Awesome ToyKeeper! Thanks for sharing your experience. It's fun stuff! I'm at the point now where my lights do what I want them to with a basic 3-mode with off-time. I'm really done tinkering with new versions of the code, programmability, flashy modes, etc. But this is great because I can now focus on other things.

Toykeeper could you please explain a bit what this is?
Can I send you a modified STAR Firmware and you will add them in this STAR Encyclopedia or what?

Werner, I’m basically just applying some of the most common “best practices” from the software world and applying them to flashlight firmware. I’m hoping it will encourage more collaboration.

In general, open-source software projects organize their activities around a project management service such as Launchpad or GitHub. This provides a central hub for storing and publishing source code and other project files, along with a system for keeping old revisions and managing code patches. It also provides bug tracking or issue tracking, along with a variety of other optional services like mailing lists or documentation systems. Plus, it’s just nice having everything in one place.

So, you could send me a modified version and I could add it to the repository for you. Or you could branch the repo, add your improvements, publish your own branch, and share it. Or submit a merge proposal to get it back into the main repository. Or you could fork the whole thing complete with history and start your own project if you don’t like the way it’s being managed.

A lot of the features are probably more than we really need, but it’s nice to have room to grow. For example, I doubt we’ll need to bisect the revision history to figure out exactly where a bug was introduced in a firmware’s code, but stuff like that is available if anyone needs it.

That sounds good, code sharing in this forum is terrible and so I am quite sure a lot of useful things fall under the carpet…

I’m not entirely sure how to use Launchpad’s revision control tools (bzr) in Windows or MacOS, but those are both supported platforms. I think both have a few GUIs available too, but I’m not familiar with them.

I just “bzr branch lp:flashlight-firmware” to get a copy of the code, and then otherwise use bzr at the command line to check in new versions or do other common operations. The only GUI part I use is “bzr vis” from bzr-gtk, which is handy for viewing the revision history. It looks like this:

This is all optional though. I’m happy to accept patches and such via email and do all the revision control and publishing steps myself.

This is not email, but wanted to post the enhanced _delay_ms() function here so that it won't get buried to another thread as OT post..

I have seen this "_delay_ms() can't take variables" so many times that it's time to do something for it:

#define OWN_DELAY
#ifdef OWN_DELAY
#include <util/delay_basic.h>
// Having own _delay_ms() saves some bytes AND adds possibility to use variables as input
static void _delay_ms(uint16_t n)
    while(n-- > 0)
#include <util/delay.h>


#ifndef OWN_DELAY
uint16_t randTime;

// turn the emitter on at a random level,
// for a random amount of time between 1ms and 20ms (* 4/3)
PWM_LVL = rand() % 190 + 10;
#ifdef OWN_DELAY
_delay_ms(rand() % 19 + 1);
randTime = rand() % 19 + 1;
while(randTime–) // _delay_ms() can’t take variables that can change, make loop with variable instead
_delay_ms(1); // and delay_ms with fixed value within loop
// turn the emitter off,
// for a random amount of time between 1ms and 1000ms (* 4/3)
PWM_LVL = 0;
#ifdef OWN_DELAY
_delay_ms(rand() % 999 + 1);
randTime = rand() % 999 + 1;

In this example, using own delay saved us 16 bytes (with -Os) and made the code cleaner.


This is good stuff. It should probably replace the standard _delay_ms() in every firmware which calls _delay_ms() more than once. On one of my STAR derivatives, this delay function saved me at least 140 bytes.

The parameter sent to _delay_loop_2() is also a handy thing to change per-driver if you want more accurate timing, since it can be calibrated for each individual chip. I’ve tried it on three now, and the value has been anywhere from 890 to 950 if I want _delay_ms(1000) to be reasonably close to one second.

I suppose I should probably update STAR with this. I may need to upgrade my avr-gcc first though, since what I have now compiles STAR to about 1060 bytes instead of 1024.

I posted this in the random flash thread, but can post it here too:

I did a shorter one some time ago so you don’t even have to include delay_basic.h. I basically just ripped out one of the assembler loops from delay_basic.h. The variable entered does not resemble a nice even millisecond value, like 1 or 10 ms or similar, but I don’t need exact millisecond numbers, I only have to adjust the value until I like what I see.

By the way, how did you post your code? It looks like code, when I try to paste in my code it looks like garbage so I post images instead. How did you get it formatted nicely like that?

I looked into it, but I needed something with fairly precise timing so I didn’t use it.

I used the HTML ‘pre’ tag.
(insert code here)

Helios made me a kewl Roche F6 driver (momentary switch) with two battery level indicators, but I have zero clue how to add whatever to the FW to make them work. They're run by MCU pin 3 & pin 5, circuits for both are totally separate so it's possible to use them one at a time or both together, to get a third color. Any suggestions for what the LEDs should do? Keep the original low voltage behavior (blink + ramp down) or ditch it?

Depends on your preference I suppose. In order to get the most mileage out of those indicators it seems that removing the ramp/step-down makes sense. Replace that with warning indications… but really I probably wouldn’t do it unless I could make the indicators pretty visible.

OTOH there’s nothing wrong with having both systems in place - a red indicator is just a confirmation that the stepdown is due to LVP.

I could use some help. I’m not sure what I need to do to move PWM from PB1 to PB0.

Here is what I have so far.

I changed:

  • the PWM_PIN define
  • the PWM_LVL define (output compare register)

I did not change the TCCR0A or TCCR0B stuff.

This is for the LD-29 project. In retrospect it may have made more sense to hookup the normal PWM pin… maybe that’s what I’ll end up doing.

Thanks in advance.