STAR Firmware by JonnyC - Source Code and Explanation

1335 posts / 0 new
Last post
Mike C
Mike C's picture
Offline
Last seen: 1 week 3 days ago
Joined: 01/22/2014 - 08:03
Posts: 2585
Location: Sweden

I’ve got a temporary setup with an adjustable DC supply and have hooked up the wires for easy access, so I’ve tried the loop myself now and it works. Doing this saves me plenty of bytes which I probably won’t need in my “final” firmware version, but now during the testing stage I can cramp more of my own code into the hex file for more extensive testing.

The below loop within a loop within a loop within a loop takes very roughly about one second (had to remove leading tabs as they don’t seem to work very well here):

A = 0;
B = 0;
C = 0;
D = 0;
while(A++ < 14) {
while(B++ < 255 ){
while(C++ < 255){
while (D++ < 255){
}
D = 0;
}
C = 0;
}
B = 0;
}

This can of coarse be made into a routine that can be called on with an argument which is then calculated to resemble milliseconds, meaning the entire _delay_ms and delay.h can be made entirely obsolete for us that do not require precise millisecond accurate timing and need a little more space for code.

wight
Offline
Last seen: 1 year 8 months ago
Joined: 11/27/2013 - 16:40
Posts: 4969
Location: Virginia, USA

When using the internal xtal I seriously doubt that _delay_ms / delay.h were accurate anyway.

Still fine, still on a break. One day I’ll catch up with you folks! previous wight catchup Wink
list of my drivers & variants (A17DD, FET+1 stuff, WIP stuff, etc)

WarHawk-AVG
WarHawk-AVG's picture
Offline
Last seen: 1 year 6 months ago
Joined: 01/04/2014 - 06:47
Posts: 5071
Location: H-Town
Cereal_killer wrote:
Mike C wrote:
I am changing the functionality of some of the features with the STAR 1.1 firmware and just want to make sure about what this line of code does: PWM_LVL = modes[- -mode_idx]; This changes the PWM_LVL (output) to the level of the previous mode but does not actually change the mode itself. This means that if this line is executed while the light is on high, the output will switch to that of medium, but the light will still “think” it’s on high and remember high as current mode if switched off. Is that correct?

Note you can also use this line to modify the turbo step down to a specific PWM value instead of the previous mode, simply replace PWM_LVL = modes[- -mode_idx]; with PWM_LVL = 180 (desired PWM value). That way you can have it step down to a level of your choice but still act normal and still be able to be bumped back up to turbo with a single click.

I use it like this in my small lights that need a large step down to not overheat.

Oh yeah…I like the turbo timeout, this way you can use very high power FETS or numerous 7135’s drive it hard (barn burner) for a few seconds and have it auto throttle back to not overheat, it’s a very good firmware Smile
ToyKeeper
ToyKeeper's picture
Offline
Last seen: 5 hours 10 min ago
Joined: 01/12/2013 - 14:40
Posts: 10809
Location: (469219) 2016 HO3

Mike C wrote:
The below loop within a loop within a loop within a loop takes very roughly about one second (had to remove leading tabs as they don’t seem to work very well here):
… {{nested loops}}

You know the problem with doing loops like that, right? It keeps the CPU active and running at near-full power, so it eats up the battery faster. It might be better to set an interrupt for some number of cycles in the future and then go to sleep, waking whenever the interrupt goes off.
wight
Offline
Last seen: 1 year 8 months ago
Joined: 11/27/2013 - 16:40
Posts: 4969
Location: Virginia, USA

You’re probably right about there being a better way. It sounds like he’s just doing it to institute brief pauses (blinks, etc) – and the CPU draws single digit milliamps. So I think it should work fine for his purpose.

I’m still interested in what you described though, do you have a link to info on setting that up for AVR’s?

Still fine, still on a break. One day I’ll catch up with you folks! previous wight catchup Wink
list of my drivers & variants (A17DD, FET+1 stuff, WIP stuff, etc)

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 5 hours 10 min ago
Joined: 01/12/2013 - 14:40
Posts: 10809
Location: (469219) 2016 HO3

No, I simply skimmed through the attiny13a reference manual, and I’ve done similar things in the past in DOS and in Linux. Looks like it works in a very similar manner… assign an interrupt handler, set the parameters for a timer, start it, then execute the instruction to put the main CPU into standby mode. It’ll then idle at low power until something wakes it up, such as the timer popping and calling the interrupt you assigned.

Mike C
Mike C's picture
Offline
Last seen: 1 week 3 days ago
Joined: 01/22/2014 - 08:03
Posts: 2585
Location: Sweden

ToyKeeper wrote:
You know the problem with doing loops like that, right? It keeps the CPU active and running at near-full power, so it eats up the battery faster. It might be better to set an interrupt for some number of cycles in the future and then go to sleep, waking whenever the interrupt goes off.

I am into learning so I might look into it, but my intended purpose with this loop is only to replace the _delay_ms() function. To me it looks like _delay_ms() is just a more complicated and byte heavier way of doing exactly what my loop does, also without using interrupts. My loop should therefor not be eating up much more CPU power than the _delay_ms() function that it’s replacing.
Or have I missed something? Is _delay_ms() using interrupts?

And besides, in the main() function of the STAR 1.1 source the while(1){} loop runs voltage monitoring (unless disabled), so the CPU is constantly doing stuff anyway. If using interrupts is optimizing for CPU load, the entire voltage monitoring function should be activated by an interrupt instead of being run in a while(1){} loop.

JonnyC
JonnyC's picture
Offline
Last seen: 7 months 1 week ago
Joined: 01/14/2011 - 19:12
Posts: 1148
Location: Green Bay, WI - USA

Mike C wrote:
And besides, in the main() function of the STAR 1.1 source the while(1){} loop runs voltage monitoring (unless disabled), so the CPU is constantly doing stuff anyway. If using interrupts is optimizing for CPU load, the entire voltage monitoring function should be activated by an interrupt instead of being run in a while(1){} loop.

If you look at the end of the while(1) loop, you'll see a "sleep_mode();" command which will go to sleep and wait for the WDT interrupt.  I didn't put it in there for power consumption though, just so that the ADC low voltage detection doesn't trigger immediately (it has to detect low voltage 8 times over 4 seconds, if I read my code right).

Mike C
Mike C's picture
Offline
Last seen: 1 week 3 days ago
Joined: 01/22/2014 - 08:03
Posts: 2585
Location: Sweden

JonnyC wrote:
If you look at the end of the while(1) loop, you’ll see a “sleep_mode();” command which will go to sleep and wait for the WDT interrupt.  I didn’t put it in there for power consumption though, just so that the ADC low voltage detection doesn’t trigger immediately (it has to detect low voltage 8 times over 4 seconds, if I read my code right).

Ahh, I see. I missed that one. I took a look at sleep_mode() and can’t make sense of what it does… at all.

But that takes me back to the _delay_ms() function. It doesn’t appear to use any interrupts. I can’t really say for sure but the code certainly has none of the mumbo jumbo that’s in sleep_mode(). To me _delay_ms() appears to be just a bunch of loops waiting for increments until they are done. Can anyone verify? Is there anything in _delay_ms() that suggests it would use less CPU load than a simple loop?

I have refined my loop a bit: (using “_” to space out the lines to make it more resemble C code)

uint8_t A = 0;
uint16_t B = 0;
uint8_t C = 0;
uint8_t X = 0;

while(A++ < X) {
_B = 0;
_while(B++ < 25850){
__C = 0;
__while(C++ == 0){} // Odd! Having nothing here makes total loop extremely fast. Adding C loop slows it down, but it does not matter how many times C loop is run, total time is same.
_}
}

X is about 0.1 seconds, so entering 10 into this argument gives about 1 second delay.

I compiled a hex file with a bunch of modes and timers that has five instances of my delay and compared it to the same code but with the _delay_ms() instead, and the difference was 249 bytes. Considering the limited space for my tests I think it’s quite useful, as it has been the difference of having a too large hex file and not.

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 5 hours 10 min ago
Joined: 01/12/2013 - 14:40
Posts: 10809
Location: (469219) 2016 HO3

I haven’t actually gotten started writing and flashing attiny firmware yet. I just figured, as long as the chip has dedicated hardware for offloading wait loops, it might be worth using. However, that would only work if that interrupt and counter aren’t already being used for something else, and it doesn’t guarantee the CPU won’t be awakened early by some other interrupt.

I’ll know more after I really have a chance to dive in and start mucking with things. I’m planning to do some stuff with variable-speed slow strobes and underclocking and clock dividers, so timing will get a bit tricky.

Mike C
Mike C's picture
Offline
Last seen: 1 week 3 days ago
Joined: 01/22/2014 - 08:03
Posts: 2585
Location: Sweden

ToyKeeper wrote:
I just figured, as long as the chip has dedicated hardware for offloading wait loops, it might be worth using.

I agree, but it appears that the _delay_ms() routine that comes with the package doesn’t use the it, so by replacing it with my loop I will not make anything worse.

It could perhaps get better with what you suggest but re-writing the existing _ms_delay() function to incorporate interrupts is way over my head. I just needed a few more bytes and, as it appears to me, I didn’t cause any increased CPU load.

Edit: If you have a look at the delay.h (which I assume comes along with AVR Studio) I think you’ll see what I mean. I’m doing the same thing as that routine, just less byte intensive, that’s all.

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 5 hours 10 min ago
Joined: 01/12/2013 - 14:40
Posts: 10809
Location: (469219) 2016 HO3

Thanks for testing this. I’ll probably be hurting for spare bytes when I start making changes, so every little bit helps.

Tom E
Tom E's picture
Offline
Last seen: 32 min 2 sec ago
Joined: 08/19/2012 - 08:23
Posts: 14993
Location: LI NY

Anyone know what cap value/size to use for off time memory? I've been post hunting, but just can't find it - not on Jonny's web site, not mentioned in the source code for STAR_off_time, not on Richard's website, can't find it here, can't find a thread for it, just can't find it, period... Help? I know it must be somewhere?? Is Jonny's STAR_off_time the only driver source code that uses it?

I believe it goes between an IO pin and ground, from a comfy pic somewhere...

wight
Offline
Last seen: 1 year 8 months ago
Joined: 11/27/2013 - 16:40
Posts: 4969
Location: Virginia, USA

Tom E wrote:

Anyone know what cap value/size to use for off time memory? I’ve been post hunting, but just can’t find it – not on Jonny’s web site, not mentioned in the source code for STAR_off_time, not on Richard’s website, can’t find it here, can’t find a thread for it, just can’t find it, period… Help? I know it must be somewhere?? Is Jonny’s STAR_off_time the only driver source code that uses it?


I believe it goes between an IO pin and ground, from a comfy pic somewhere…


1uF works well and is the specified value. It’s in the OP waaaay at the bottom. Other values work too though, HarleyQuin investigates this on page 5 of this thread.

In terms of other firmwares that use a cap, Tido’s firmware (BLF-VLD) supports offtime but I don’t remember if it worked with just a cap or a cap and a resistor or what.

Still fine, still on a break. One day I’ll catch up with you folks! previous wight catchup Wink
list of my drivers & variants (A17DD, FET+1 stuff, WIP stuff, etc)

Microa
Offline
Last seen: 19 hours 39 min ago
Joined: 06/29/2011 - 21:20
Posts: 251

If my memory is correct, the cap is 1uF X7R 0805 size and is connected between pin2 (PB3) and ground.

locusto03
Online
Last seen: 9 min 49 sec ago
Joined: 03/03/2014 - 01:35
Posts: 302

Tom E wrote:

Anyone know what cap value/size to use for off time memory? I've been post hunting, but just can't find it - not on Jonny's web site, not mentioned in the source code for STAR_off_time, not on Richard's website, can't find it here, can't find a thread for it, just can't find it, period... Help? I know it must be somewhere?? Is Jonny's STAR_off_time the only driver source code that uses it?

I believe it goes between an IO pin and ground, from a comfy pic somewhere...

 

I got the ones recommended by comfychair:

 

http://www.ebay.com/itm/181283883536

 

The easiest would be to solder it to the 4th star and grounding ring, but there are other options. Others should be able to help with that...

Tom E
Tom E's picture
Offline
Last seen: 32 min 2 sec ago
Joined: 08/19/2012 - 08:23
Posts: 14993
Location: LI NY

Thanks all! I ordered those caps off of the eBay link. I missed mentioning of the cap value in the OP. My links to posts don't see to work - very frustrating... The comfychair link I could not find

allan d
Offline
Last seen: 3 months 2 weeks ago
Joined: 09/01/2012 - 00:15
Posts: 338
Location: SW Florida & SoCal

I put the cap between star 4 and the ground ring on the 105c. For the AK-47A I want to keep the bottom free of components so I put the cap on two pads marked R4. It connects pin 2 and ground just like using the 4th star.

The 101-AK-A1 is a little more difficult, there is no straight forward location for the cap. I haven’t done one yet, I just stack 7135s on an AK-47 if I want more than 1 amp with a flat bottom driver.

Allan

comfychair
comfychair's picture
Offline
Last seen: 5 years 7 months ago
Joined: 01/12/2013 - 05:39
Posts: 6198

Tom E wrote:
My links to posts don't see to work - very frustrating...

You are not the only one - it seems different people are using a different number of posts per page, so a link to a specific post that works for one person is broken for somebody else. Site really shouldn't require the page number in links to specific posts, or something. Links in notification emails don't work either for the same reason I think.

I can only get to the post in that link by changing the '?page=7' to '?page=4' - http://budgetlightforum.com/node/29150?page=4#comment-573278

Tom E
Tom E's picture
Offline
Last seen: 32 min 2 sec ago
Joined: 08/19/2012 - 08:23
Posts: 14993
Location: LI NY

Oh -- found out more... I had my setting at 150/page while locusto03 must be using 30/page (experimented til I found one that worked). I set mine to 50/page, thinking that's the default?? Not sure...

allan d
Offline
Last seen: 3 months 2 weeks ago
Joined: 09/01/2012 - 00:15
Posts: 338
Location: SW Florida & SoCal

Mine is set to 50/page. Don’t know if that is default or if I made the change.

Allan

Helios-
Helios-'s picture
Offline
Last seen: 2 years 1 week ago
Joined: 01/18/2012 - 21:12
Posts: 2099

150 here.




comfychair wrote:
Site really shouldn’t require the page number in links to specific posts, or something. Links in notification emails don’t work either for the same reason I think.


Counterfeit 18650s, 2,<a href=“http://

ToyKeeper
ToyKeeper's picture
Offline
Last seen: 5 hours 10 min ago
Joined: 01/12/2013 - 14:40
Posts: 10809
Location: (469219) 2016 HO3

I’ve been wondering about the specific post links too. I don’t have a solution, but I try to reduce the issue by using links compatible with the default page size. The default is 30, which I checked by viewing BLF in a browser with no login and no cookies.

Helios-
Helios-'s picture
Offline
Last seen: 2 years 1 week ago
Joined: 01/18/2012 - 21:12
Posts: 2099

I add the post number so people can find it despite a broken link.
Post #352


Counterfeit 18650s, 2,<a href=“http://

JonnyC
JonnyC's picture
Offline
Last seen: 7 months 1 week ago
Joined: 01/14/2011 - 19:12
Posts: 1148
Location: Green Bay, WI - USA

Post #122 has the link to Digi-Key for the capacitors I use.

http://budgetlightforum.com/node/29150?page=4#comment-549072

Yojimbo
Offline
Last seen: 7 years 5 months ago
Joined: 06/13/2014 - 07:50
Posts: 5

Is it possible that driver intended for P60 module (so simple on/off as UI) has hidden modes?

comfychair
comfychair's picture
Offline
Last seen: 5 years 7 months ago
Joined: 01/12/2013 - 05:39
Posts: 6198

I built one that has a pseudo-hidden strobe... modes are 255, 255, 255, 255, STROBE, with no memory. Turning on/off or accidentally bumping the switch it pretends to not change modes, but you can get to the strobe if you need it.

Yojimbo
Offline
Last seen: 7 years 5 months ago
Joined: 06/13/2014 - 07:50
Posts: 5

Thanks comfychair. Yes, it is logical to make approach that way, I will probably end up with something like that. But here is a new idea:

If the modes in one setup are called a group of modes, how hard is to implement two groups? So group 1 would be low-medium-high but if we click (not click but tap or momentarily activate light without click) certain number of times it would change the whole group. Maybe fast clicks and it’s not low-medium-high any more but group 2 which is strobe-high, for example. Fast clicking 10 times goes back to low-medium-high.

JonnyC
JonnyC's picture
Offline
Last seen: 7 months 1 week ago
Joined: 01/14/2011 - 19:12
Posts: 1148
Location: Green Bay, WI - USA

Yojimbo wrote:
Thanks comfychair. Yes, it is logical to make approach that way, I will probably end up with something like that. But here is a new idea: If the modes in one setup are called a group of modes, how hard is to implement two groups? So group 1 would be low-medium-high but if we click (not click but tap or momentarily activate light without click) certain number of times it would change the whole group. Maybe fast clicks and it's not low-medium-high any more but group 2 which is strobe-high, for example. Fast clicking 10 times goes back to low-medium-high.

Check out some of the other programs out there, including BLF-VLD and luxdrv.  I can't remember but I think one of those has mode groups.

Mike C
Mike C's picture
Offline
Last seen: 1 week 3 days ago
Joined: 01/22/2014 - 08:03
Posts: 2585
Location: Sweden

ToyKeeper wrote:
Thanks for testing this. I’ll probably be hurting for spare bytes when I start making changes, so every little bit helps.

I’ve been playing around a lot lately with optimizing for size and have managed to do a slimed down version of STAR 1.1. Mine basically does everything that STAR 1.1 does except check for soldered stars. I removed all those checks and did those selections by using a bunch of #IFDEF and #ELSE sequences. I saved quite a few bytes doing this. Personally I have no use for soldering stars, if I want to change the things the stars changed I’ll just flash a driver with the changes.

I also made a new delay loop by stealing a small section of code from delay_basic.h. My time resolution is not good (77ms) but for my purposes I can get the delays I want, I don’t need pin point accuracy.

Then I edited the voltage monitoring sequence quite a lot, removed a bunch of while loops and delay loops, and saved a total 278 bytes on the original STAR 1.1… That leaves me with plenty of room for playing around Smile

I’m no programmer though. I’ve tested the functionality with the help of a variable DC power supply, seems to be running fine but I guess I’ll see once it’s been built into a light.

Pages