From d915fd32a7becdf0f0492960fa5b241ee407aee9 Mon Sep 17 00:00:00 2001 From: Sarah Wilson Date: Fri, 10 Jan 2025 20:09:05 +1100 Subject: Initial version --- main.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 main.c (limited to 'main.c') diff --git a/main.c b/main.c new file mode 100644 index 0000000..5c8bc76 --- /dev/null +++ b/main.c @@ -0,0 +1,182 @@ +#include + +#include +#include +#include + +#define max(a, b) \ + ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; \ + }) + +#define min(a, b) \ + ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a < _b ? _a : _b; \ + }) + +// return a + (t/128)*(b-a) +static uint8_t lerp(uint8_t a, uint8_t b, uint8_t t) +{ + return a + (uint8_t)(((int16_t)(b - a) * t) >> 7); +} + +static void eeprom_write(uint16_t addr, uint8_t data) +{ + while (EECR & _BV(EEPE)) + ; + EEAR = addr; + EECR = 0; + EEDR = data; + EECR |= _BV(EEMPE); + EECR |= _BV(EEPE); +} + +static uint8_t eeprom_read(uint16_t addr) +{ + while (EECR & _BV(EEPE)) + ; + EEAR = addr; + EECR = _BV(EERE); + return EEDR; +} + +enum { + MODE_SOLID = 0, + MODE_PULSE, + MODE_ALTERNATE, + MODE_FAST_PULSE, + MODE_FAST_ALTERNATE, + MODE_VFAST_PULSE, + MODE_VFAST_ALTERNATE, + NUM_MODE, +}; + +uint16_t tickcount; +static void tick(void); + +ISR(TIM0_COMPA_vect) +{ + ++tickcount; + tick(); +} + +static uint8_t mode; +ISR(PCINT0_vect) +{ + static uint16_t down; + + if ((PINB & _BV(PB0)) == 0) { + down = tickcount; + } else { + if (tickcount - down > 100) { + eeprom_write(0, mode); + } else { + if (++mode == NUM_MODE) { + mode = MODE_SOLID; + } + } + } +} + +static uint8_t brightness; +ISR(ADC_vect) +{ + brightness = ADCH; +} + +static uint8_t oa_duty, ob_duty; +ISR(TIM1_OVF_vect) +{ + OCR1A = min(oa_duty, 127); + OCR1B = max(255 - ob_duty, 128); +} + +void tick(void) +{ + ADCSRA |= _BV(ADSC); + + switch (mode) { + case MODE_SOLID: + oa_duty = ob_duty = brightness >> 1; + break; + case MODE_PULSE: + case MODE_ALTERNATE: + case MODE_FAST_PULSE: + case MODE_FAST_ALTERNATE: + case MODE_VFAST_PULSE: + case MODE_VFAST_ALTERNATE: { + static uint8_t dir; + static uint8_t t; + + oa_duty = lerp(0, brightness >> 1, dir ? t : 128 - t); + ob_duty = (mode & 1) ? oa_duty : ((brightness >> 1) - oa_duty); + t += mode > MODE_FAST_ALTERNATE ? 4 : + mode > MODE_ALTERNATE ? 2 : + 1; + if (t >= 128) { + t = 0; + dir = !dir; + } + } break; + } +} + +static void pwm_init(void) +{ + TCCR1 = _BV(PWM1A) | _BV(COM1A1); + GTCCR |= _BV(PWM1B) | _BV(COM1B1) | _BV(COM1B0); + + TCCR1 |= _BV(CS12); + + OCR1A = 0; + OCR1B = 255; + + DDRB |= _BV(PB1) | _BV(PB4); + + TIMSK |= _BV(TOIE1); +} + +static void adc_init(void) +{ + ADMUX = _BV(ADLAR) | _BV(MUX0) | _BV(MUX1); + DIDR0 = _BV(ADC3D); + ADCSRA = _BV(ADEN) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1); +} + +static void tick_init(void) +{ + GTCCR = _BV(TSM) | _BV(PSR0); + TCCR0A = _BV(WGM01); + TCCR0B = _BV(CS01) | _BV(CS00); + OCR0A = 122; // 1M/64 = 15kHz / 122 = 128 hz tick + TIMSK |= _BV(OCIE0A); + GTCCR &= _BV(TSM); +} + +int main(void) +{ + mode = eeprom_read(0); + if (mode >= NUM_MODE) { + mode = 0; + } + + tick_init(); + pwm_init(); + adc_init(); + + DDRB &= ~_BV(PB0); + PORTB |= _BV(PB0); + GIMSK = _BV(PCIE); + PCMSK = _BV(PCINT0); + + sei(); + + for (;;) + sleep_mode(); + + return (0); +} -- cgit v1.2.3