STAR Firmware by JonnyC - Source Code and Explanation

Ok - I fixed it now. First, I re-produced it on another Nanjg 101-AK-A1 (short story: 1st light sold as soon as I showed it to someone...). This was a 2.45A build, but same exact firmware of STAR_NoInit. It has the same exact problem, but this time I notice after the 3 blinks, it actually turns off for a couple secs, then turns on at a moon mode level -- weird.

So again, I studied the code and only possible issue I could see is the manipulations of ALT_PWM_LVL, which is really the I/O register OCR0A. So, I added a variable called: 'setPwmOut' that mirror images the PWM output, and referenced it instead of ALT_PWM_LVL in the LVP code. Then viola!! Re-built and works perfectly. You can see it now go thru 3 blinks, then drop, repeatedly, which is how it should work. Also I fixed a potential bug in the Main LVP code where mode_idx is decremented where it could potentially be 0 before the decrement.

The decrement is below this comment (code inserting sux in a thread post), add an if " if (mode_idx > 0)" before "mode_idx++":

// See if we should change the current mode level if we've gone under the current mode.

Ohhh - I use AtmelStudio 6.2 with the optimized for size setting - all same compile/build settings as my eswitch and STAROffTime projects which work well, including LVP.

Awesome. Could you send me a patch, or the source you’re now using? I’d like to fix it in my repo too.

Sure.. My version has some additional formatting changes, always backs off the mode index by 1 when a turbo timeout occurs (so 1 click restores turbo), and disables the moon mode STAR setting (commented out). @work now with no access to it, but I'll try this eve. You probably should grab all my latest to update your repository with. I'll try to throw together some readme text files for each to list the changes/enhancements.

Really love the quick click mode change of this noinit version. The OTC cap versions always seem to have issues of variation of timing, and so far, this one has been a rock. From what I can see, the 2 main changes to the fuses is the 64 msec delay option vs. the 4 msec delays option, and the brown-out detection enabling. Thinking the 64 msecs give it more time for the memory to change, so the timing of the mode change detection is better/shorter. The brown-out detection enabling is the key to it working at all, I would think.

When you say "mirrored" do you mean reversed? or do you mean copied?

Smile - in CS/IT, never heard of mirror imaging doing anything reverse - interesting analogy.. I mean copy, a local copy of the I/O register.

It's an old trick (I'm old too) to have a local copy of registers, specially when they are write-only. These registers (OCR0A and OCR0B) are doc'd as R/W, so either there's something quirky with them, or the C compiler has some bug/issue with doing manipulations on registers, dunno, or could be some flaky bug in our software that somehow corrupts something, and my change simply moved things around so the effect is minimized. I've seen it all from chip bugs to SW tool bugs, and got burned a few times on C compiler problems. We've had a few C compiler bugs on our current project at work using a TI DSP and the development tools that support them. Back in the mid-late 80's and 90's, I believe the compilers were better - they were developed in the US either directly by the chip manufacturer or direct contractor. Now everything goes overseas and the rigorous quality and testing standards have diminished. It's all bout saving money now...

Sorry - That's my engineer curse throwing doubt in my interpretations. Anyone else would know exactly what you meant.

I figured you meant 'copy', and now upon further refection, I can't imagine why you would 'reverse' it, but I asked first and thought second.

I did it because I can :stuck_out_tongue: . And now I have a spare programmer in case one goes Tango Uniform.

…And what did it cost me? $3 and maybe 2 hours of net surfing/zapping.

I had to go byte hunting again, both in program space and available RAM, to fit in a function in a light that has a 13A MCU. I still had some code left from the original Star and found a way to free up some much needed space.

The eeprom_read_block funtion eats a fair chunk of programming space and the eep array eats half of the 13A’s RAM capacity.

eeprom_read_block(&eep, 0, 32);
while((eep[eepos]==0xff) && (eepos<32)) eepos++;

Instead of reading a 32 byte block, read one byte at a time.

while (modeidx==0xff && eepos<64) {
    while (EECR & 2);
    EEARL = eepos;  EECR = 1; modeidx = EEDR;
    while (EECR & 2);
    if (modeidx==0xff) eepos++;
}

There are only advantages to this. Not only did it save me 32 bytes of programming space, it frees up the 32 byte eep array just hanging around eating up half of the 13A’s RAM capacity, and it also allows using the full 64 bytes of the EEPROM for wear leveling. I can’t notice any difference in mode reading time either, and I tested with the full 64 byte wrap around.

I probably don’t have to do the second wait after reading, but I need to be sure that no EEPROM reading or writing is going on before continuing. If I have to hunt down a few more bytes I’ll take a closer look at that…

Mike C, I did the same thing in the blf-a6 firmware. :slight_smile:

So, the blf-a6 code can be used as a reference for handling eeprom more space-efficiently. It also shows how to store multiple values, if desired, or how to store just the mode index. (full blf-a6 uses multiple values, trimmed-down version just stores one value)

BTW, there are some library functions which can be used instead of accessing the eeprom registers directly. This should make the code a little more portable to different MCUs, and might also make the code smaller or less likely to break.

BTW, I’m not really sure where to announce this, but I added a tagging system and an auto-generated index to the firmware repository. I hope this will make it easier for people to find code relevant to their needs.

The latest index should always be here:

http://bazaar.launchpad.net/~toykeeper/flashlight-firmware/trunk/view/head:/INDEX

Nice. I usually end up throwing a few features out the window (Star functionality; LVP blinks, etc.) whenever I need more space, but I'm too lazy and ignorant to do anything more advanced!

I expected someone to have done it, but usually only check standard Star as reference, too many firmwares to go through. You could probably further optimize it by using the brownout detection method for those fast presses instead of storing them in the EEPROM. By doing this you can fit everything you need to store in a single byte. You’ve probably already done it though, but in another firmware :slight_smile:

Once I’m done with the 85 firmware I’ll just switch to it on all future builds, they don’t cost that much more and with some pin bending they fit nicely on the 13A footprint. This byte hunting is sometimes too time consuming. Still have some 13As to use up though, which is why I’m still at it.

Nice with that firmware repository. Might have to get me a trunk there and upload some stuff someday, but it might not be of use to many as I’m using totally different pins than the standard 105 layout. None of my firmwares are directly compatible with them.

I haven’t tried mixing brownout plus eeprom yet, but I may have to do a quick mod to see if it ends up using less space. :slight_smile:

Go for it! I think people would be very interested to see your code, especially because you’re using different MCUs and different pin layouts. We could use some fresh ideas around here. :slight_smile:

Since it’s not really STAR any more, it might be good to switch over to a different thread to avoid cluttering this one any more. I know I’ve dumped too much off-topic stuff in other threads, so I made a new thread for firmware in general:

I would imagine we could also use a thread for info on your driver hardware, if you’re willing to write up the details. I liked the M6 “BMF” thread, and would love to read more about your other work.

I’m actually confused here… subtle changes in code make huge differences in bytes used. I think it’s the optimize for size that does a pretty good job when it can, then when it can’t optimize the difference is pretty big. Not experienced with with stuff at all. Working with the volatile bytes takes memory, but so does static bytes.

Anyhow, the latest 13A code I’m writing uses brownout for all presses, and a measurement of the offtime cap for short presses. Ditched long presses altogether.

I might have missed it, so I ask for help:
I am using a zener modded FET version of nanjg driver. I am trying to adjust the low voltage warning for 2s cells.
Are the following correct & enough for that?
#define ADC_LOW 260 // When do we start ramping
#define ADC_CRIT 240 // When do we shut the light off

What resistors? You can't go to 260; 255 is the limit.

* To find out what value to use, plug in the target voltage (V) to this equation
* value = (V * 4700 * 255) / (23800 * 1.1)
*
Followed above. Totally wrong?

The hardware can only use values from 0 to 255. Anything outside that range can’t be handled by code, and requires changing the resistor values instead.

In general, you probably want to keep your values near the middle of that range and not go all the way to the edges. Measurement can get a little weird at the extremes.

Also, you’ll get more precise results by measuring the actual ADC values instead of relying on a formula. But that assumes you already have the resistors configured to give you usable values. The formulas should get you pretty close though.

Can somebody share the resistor values for 2 & 3s configuration?

Anyone can help me with my problem? I built this driver [WIP] 17mm DD+single-7135 driver / single sided / Dual-PWM and installed the blf-a6 firmware. In battcheck mode i always get 5 blinks even if the voltage of the battery is 3.0v. So i flashed it with battcheck firmware to calibrate it but i always get 2-5-5 blinks at whatever voltage of the battery. I am using 22k for R1 and 4.7k R2, do you think that is the problem?