#include #include #include #include #include "ledpwmcurve.h" #define PWMMin 128 #define PWMMax 1024 #define PWMRange (PWMMax - PWMMin) #define PWMRandomValue() ((random() % PWMRange) + PWMMin) #define DelayMin 5 #define DelayMax 50 #define DelayChange 1 #define DelayChangeSteps ((DelayMax - DelayMin) / DelayChange) void var_delay_ms(int n); int main() { uint16_t currentValue = PWMRandomValue(); uint16_t targetValue = currentValue; uint16_t startValue = currentValue; uint16_t speedUpUntil = currentValue; uint16_t slowDownFrom = currentValue; uint8_t delay = DelayMax; #define goingUp (targetValue > currentValue) // -- Set up PWM // Set all ports as output (leave none as floating input) DDRB = 0b11111111; // Set Timer 0 to internal clock, no prescaling. // See chapter 11.9 of the ATTiny85 datasheet TCCR0B |= (1 << CS00); // Set to 'Fast PWM' mode TCCR0A |= (1 << WGM01) | (1 << WGM00); // Clear OC0B output on compare match, upwards counting TCCR0A |= (1 << COM0B1); while (1) { if (targetValue == currentValue) { do { targetValue = PWMRandomValue(); } while (targetValue == currentValue); startValue = currentValue; speedUpUntil = goingUp ? startValue + DelayChangeSteps : startValue - DelayChangeSteps; slowDownFrom = goingUp ? targetValue - DelayChangeSteps : targetValue + DelayChangeSteps; } if (goingUp) { currentValue++; if (currentValue < speedUpUntil) delay -= DelayChange; else if (currentValue > slowDownFrom) delay += DelayChange; else delay = DelayMin; } else { currentValue--; if (currentValue > speedUpUntil) delay -= DelayChange; else if (currentValue < slowDownFrom) delay += DelayChange; else delay = DelayMin; } // Update PWM value OCR0B = antilog(currentValue); var_delay_ms(delay); } return 0; } // Source: http://www.avrfreaks.net/forum/how-use-delay-variable void var_delay_ms(int n) { while(n--) _delay_ms(1); }