Initial commit
This commit is contained in:
commit
ae0fef4b06
|
@ -0,0 +1,2 @@
|
|||
.pioenvs
|
||||
*.sublime-workspace
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"folders":
|
||||
[
|
||||
{
|
||||
"path": ".",
|
||||
"file_exclude_patterns": ["*.sublime-project"]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; http://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:attiny85]
|
||||
platform = atmelavr
|
||||
board = attiny85
|
||||
upload_protocol = stk500v1
|
||||
upload_flags = -P$UPLOAD_PORT -b$UPLOAD_SPEED
|
||||
board_f_cpu = 1000000L
|
||||
|
||||
upload_port = COM7
|
||||
upload_speed = 19200
|
|
@ -0,0 +1,66 @@
|
|||
#include <stdint.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include "ledpwmcurve.h"
|
||||
|
||||
// Source: https://electronics.stackexchange.com/a/118120
|
||||
|
||||
// Anti-Log (reverse) lookup table
|
||||
// y = 0-255 (pwm output), y_range=256
|
||||
// x = 0-1023 (10-bit ADC input);
|
||||
// assuming lower/higher end of ADC out values cannot be used
|
||||
// discarding first 32 and last 32 values.
|
||||
// min_x = 32, max_x = 1023-min_x, x_range=1024-2*min_x
|
||||
// ANTI_LOG[y] = round( x_range*log(y, base=y_range) + min_x )
|
||||
// given a value of x, perform a binary lookup on below table
|
||||
// takes about 28uS for Attiny85 @8MHz clock
|
||||
const uint16_t ANTI_LOG[] PROGMEM =
|
||||
{
|
||||
0x0000, 0x0020, 0x0098, 0x00de, 0x0110, 0x0137, 0x0156, 0x0171, 0x0188, 0x019c, 0x01af, 0x01bf, 0x01ce, 0x01dc, 0x01e9, 0x01f5,
|
||||
0x0200, 0x020a, 0x0214, 0x021e, 0x0227, 0x022f, 0x0237, 0x023f, 0x0246, 0x024d, 0x0254, 0x025b, 0x0261, 0x0267, 0x026d, 0x0273,
|
||||
0x0278, 0x027d, 0x0282, 0x0288, 0x028c, 0x0291, 0x0296, 0x029a, 0x029f, 0x02a3, 0x02a7, 0x02ab, 0x02af, 0x02b3, 0x02b7, 0x02bb,
|
||||
0x02be, 0x02c2, 0x02c5, 0x02c9, 0x02cc, 0x02cf, 0x02d3, 0x02d6, 0x02d9, 0x02dc, 0x02df, 0x02e2, 0x02e5, 0x02e8, 0x02eb, 0x02ed,
|
||||
0x02f0, 0x02f3, 0x02f5, 0x02f8, 0x02fa, 0x02fd, 0x0300, 0x0302, 0x0304, 0x0307, 0x0309, 0x030b, 0x030e, 0x0310, 0x0312, 0x0314,
|
||||
0x0317, 0x0319, 0x031b, 0x031d, 0x031f, 0x0321, 0x0323, 0x0325, 0x0327, 0x0329, 0x032b, 0x032d, 0x032f, 0x0331, 0x0333, 0x0334,
|
||||
0x0336, 0x0338, 0x033a, 0x033c, 0x033d, 0x033f, 0x0341, 0x0342, 0x0344, 0x0346, 0x0347, 0x0349, 0x034b, 0x034c, 0x034e, 0x034f,
|
||||
0x0351, 0x0352, 0x0354, 0x0355, 0x0357, 0x0358, 0x035a, 0x035b, 0x035d, 0x035e, 0x0360, 0x0361, 0x0363, 0x0364, 0x0365, 0x0367,
|
||||
0x0368, 0x0369, 0x036b, 0x036c, 0x036d, 0x036f, 0x0370, 0x0371, 0x0372, 0x0374, 0x0375, 0x0376, 0x0378, 0x0379, 0x037a, 0x037b,
|
||||
0x037c, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x038c, 0x038e,
|
||||
0x038f, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e,
|
||||
0x039f, 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ab, 0x03ac, 0x03ad,
|
||||
0x03ae, 0x03af, 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03ba, 0x03bb,
|
||||
0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03bf, 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c7, 0x03c8,
|
||||
0x03c9, 0x03ca, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03cd, 0x03ce, 0x03cf, 0x03d0, 0x03d0, 0x03d1, 0x03d2, 0x03d3, 0x03d3, 0x03d4,
|
||||
0x03d5, 0x03d6, 0x03d6, 0x03d7, 0x03d8, 0x03d8, 0x03d9, 0x03da, 0x03db, 0x03db, 0x03dc, 0x03dd, 0x03dd, 0x03de, 0x03df, 0x03df
|
||||
};
|
||||
|
||||
// Binary lookup using above table
|
||||
uint8_t antilog(uint16_t value)
|
||||
{
|
||||
uint8_t result = 0x80;
|
||||
uint16_t lookupValue;
|
||||
|
||||
for(uint16_t jumpOffset = 0x40; jumpOffset > 0; jumpOffset >>= 1)
|
||||
{
|
||||
lookupValue = pgm_read_word_near(ANTI_LOG + result);
|
||||
if (lookupValue > value)
|
||||
{
|
||||
result -= jumpOffset;
|
||||
}
|
||||
else if (lookupValue < value)
|
||||
{
|
||||
result |= jumpOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (pgm_read_word_near(ANTI_LOG + result) > value)
|
||||
{
|
||||
result -= 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef __LEDPWMCurve
|
||||
#define __LEDPWMCurve
|
||||
|
||||
extern uint8_t antilog(uint16_t value);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,106 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#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);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
& platformio run --target upload
|
Loading…
Reference in New Issue