I just asked grok if it could write me code for flashlight firmware. It said yes. Then asked me this…
“”““Let me know what behavior you want (e.g. 3 modes + moon, long-press strobe, low voltage shut-off, memory, etc.) and I can give you a more tailored version. Also tell me whether you use a power MOSFET or AMC7135 chips — that sometimes affects PWM polarity or frequency choice.””“”
So I asked for 2 modes using 7135 chips. 100% and Tactical Strobe.
Here is what it wrote.
“”“”"Here’s a tailored ATtiny13(A) firmware for your flashlight driver using AMC7135 chips.Key features:2 modes: Mode 0: 100% (full brightness, PWM = 255)
Mode 1: Tactical strobe (~13–15 Hz, 50% duty cycle) — common for disorienting effect without being annoyingly fast.
Switching: Short press to cycle modes (100% → strobe → off → 100% …)
Off: Long press (>0.4 s) to turn off from any mode
No mode memory (starts off on power-up/reset)
PWM on PB1 (standard for most 7135 drivers like Nanjg/Qlite)
Button on PB0 (active low, internal pull-up)
Debounce and basic long-press detection
Assumes factory fuses (~1.2 MHz internal, or set to 1 MHz if you changed prescaler)
For AMC7135 drivers, PWM is non-inverting — higher OCR0B value = brighter (0 = off, 255 = full on). That’s standard in almost all 7135-based firmwares
Code it wrote.
// ======================================================================
// ATtiny13(A) 2-mode flashlight driver for AMC7135
// Modes: 100% constant + Tactical strobe (~13-15 Hz)
// Short click: next mode Long press (>400 ms): off
// PB0 = button (to GND, active low)
// PB1 = PWM to AMC7135 chain
// Compile: avr-gcc -mmcu=attiny13 -Os -DF_CPU=1200000UL -o fw.elf main.c
// ======================================================================
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#define BTN_PIN PB0
#define PWM_PIN PB1
// Tactical strobe: ~13-15 Hz (common tactical range), 50% duty
#define STROBE_ON_MS 35
#define STROBE_OFF_MS 35
#define STROBE_PERIOD (STROBE_ON_MS + STROBE_OFF_MS) // ~70 ms → ~14.3 Hz
// Long press threshold (ms)
#define LONG_PRESS_MS 400
// PWM values (0-255)
#define PWM_FULL 255
#define PWM_OFF 0
volatile uint8_t mode = 0; // 0 = off, 1 = 100%, 2 = strobe
volatile uint8_t need_update = 1; // flag to update PWM/strobe in main loop
// Simple non-blocking delay helper using timer (but we use _delay_ms mostly)
static inline void debounce_delay(void) {
_delay_ms(25);
}
int main(void) {
// Setup I/O
DDRB = (1 << PWM_PIN); // PB1 output (PWM)
PORTB = (1 << BTN_PIN); // PB0 pull-up for button
// Timer0: Fast PWM, non-inverting on OC0B (PB1), prescaler /1
TCCR0A = (1 << COM0B1) | (1 << WGM01) | (1 << WGM00); // Fast PWM mode 7
TCCR0B = (1 << CS00); // prescaler 1
OCR0B = PWM_OFF; // start off
// Enable global interrupts (for future pin-change if you want wake from sleep)
sei();
while (1) {
// Button handling
if (bit_is_clear(PINB, BTN_PIN)) { // button pressed
debounce_delay();
uint16_t hold_time = 0;
while (bit_is_clear(PINB, BTN_PIN)) { // wait for release or long press
_delay_ms(10);
hold_time += 10;
if (hold_time >= LONG_PRESS_MS) {
// Long press → force off
mode = 0;
need_update = 1;
// Wait for release to avoid immediate re-trigger
while (bit_is_clear(PINB, BTN_PIN)) {
_delay_ms(5);
}
_delay_ms(200); // extra anti-bounce
break;
}
}
if (hold_time < LONG_PRESS_MS) {
// Short press → next mode
mode = (mode + 1) % 3; // 0→1→2→0...
need_update = 1;
_delay_ms(200); // debounce / prevent double click
}
}
// Update output when mode changes
if (need_update) {
need_update = 0;
if (mode == 0) {
OCR0B = PWM_OFF;
}
else if (mode == 1) {
OCR0B = PWM_FULL; // 100%
}
// mode 2 = strobe handled in loop below
}
// Strobe logic (runs continuously when mode==2)
if (mode == 2) {
OCR0B = PWM_FULL;
_delay_ms(STROBE_ON_MS);
OCR0B = PWM_OFF;
_delay_ms(STROBE_OFF_MS);
}
else {
// In non-strobe modes, just idle/sleep if you want lower power
// But for simplicity we busy-wait here (tiny code size)
_delay_ms(10); // small sleep-like delay
}
}
return 0;
}
Usage notes:Short click: cycles off → 100% → strobe → off …
Long press (hold ~0.4–0.5 s): turns off immediately from any mode
Strobe is ~14 Hz (adjust STROBE_ON_MS / STROBE_OFF_MS if you want faster/slower; 10–20 Hz is typical “tactical”)
Code is ~400–500 bytes compiled — plenty of room to add low-voltage protection later (ADC on PB2/3/4)
Possible improvements you might want next:Add low-voltage warning/shutdown (read ADC)
Mode memory (save last mode in EEPROM)
Different strobe frequency or random strobe
Moonlight mode as mode 0
Reverse polarity protection reminder (common in 7135 boards already)
Let me know if you want any of those added, or if the strobe feels too fast/slow after testing! Also, if your switch is momentary vs. latching, or if you prefer different UI (e.g. double-click for strobe), just say. Good luck with the build!“”“”"