-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWhoopPoliceLights_attiny10.ino
137 lines (118 loc) · 3.8 KB
/
WhoopPoliceLights_attiny10.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* Whoop Police Lights by Andrey Voroshkov (BShep)
* Inspired by Artem Shubin
*/
#include <avr/io.h>
#define BIGDELAY 70
#define SMALLDELAY 30
#define BRIGHTNESS_RISE_SPEED_FACTOR 2
#define BRIGHTNESS_FALL_SPEED_FACTOR 4
#define RED (1 << PB1)
#define BLUE (1 << PB0)
void delay (int millis) {
for (volatile unsigned int i = 34*millis; i>0; i--);
}
void blink(int pins, int count) {
for(int i = 0; i < count; i++) {
PORTB = pins; // write output to specified pins
delay(BIGDELAY);
PORTB = 0; // clear all port pins (set to zero)
delay(SMALLDELAY);
}
}
void startPWM() {
TCCR0A = 1<<COM0A1 | 1<<COM0B1 | 1<<WGM00; // Toggle OC0A and OC0B, Fast PWM 8bit mode TOP=0xFF
TCCR0B = 1<<WGM02 | 1<<CS00; // Fast PWM 8 bit; no prescaler
}
void stopPWM() {
TCCR0A = 1<<WGM00; // disconnect OC0A and OC0B, allow normal port operation, Fast PWM 8bit mode
TCCR0B &= ~(3<<CS00); // detach OC0A and OC0B to allow using PB0 and PB1
}
void flashLightIteration(int * val, uint8_t * phase, uint8_t riseSpeed, uint8_t fallSpeed, uint8_t phase3Delay) {
if (*phase == 0) {
*val = *val + *val/riseSpeed + 1;
if (*val > 254) {
*val = 255;
*phase = 1;
}
} else if (*phase == 1) {
*val = *val - *val/fallSpeed;
if (*val <= fallSpeed ) {
*phase = 2;
*val = phase3Delay; // this is a light-off delay
}
} else {
*val = *val - 1;
if (*val == 1) {
*phase = 0;
}
}
}
void blueFlashLightIteration() {
static int val = 0;
static uint8_t phase = 0;
flashLightIteration(&val, &phase, BRIGHTNESS_RISE_SPEED_FACTOR, BRIGHTNESS_FALL_SPEED_FACTOR, 5);
if (phase == 2) {
OCR0A = 0;
} else {
OCR0A = val;
}
TCNT0 = 255; // OCR0x is only set when counter value reaches the top
}
void redFlashLightIteration() {
static int val = 200;
static uint8_t phase = 0;
flashLightIteration(&val, &phase, BRIGHTNESS_RISE_SPEED_FACTOR, BRIGHTNESS_FALL_SPEED_FACTOR, 6); // phase3Delay=6 gives a bit bigger delay than 5 for blue, thus producing a slight disbalance to make it more real
if (phase == 2) {
OCR0B = 0;
} else {
OCR0B = val;
}
TCNT0 = 255; // OCR0x is only set when counter value reaches the top
}
#define SPEED_BLINK_COUNT 7
int main (void) {
DDRB = 0b0011; // Pins 0, 1 - output;
while (1) {
// ---------- effect #1 -----------
for(uint8_t i = 0; i < 6; i++) {
blink(RED, SPEED_BLINK_COUNT);
delay(SMALLDELAY);
blink(BLUE, SPEED_BLINK_COUNT);
delay(SMALLDELAY);
}
delay(100);
// ---------- effect #2 -----------
for(uint8_t i = 0; i < 6; i++) {
PORTB = RED;
delay((SMALLDELAY+BIGDELAY) * SPEED_BLINK_COUNT/4);
PORTB = 0;
delay((SMALLDELAY+BIGDELAY) * SPEED_BLINK_COUNT/2);
PORTB = BLUE;
delay((SMALLDELAY+BIGDELAY) * SPEED_BLINK_COUNT/4);
PORTB = 0;
delay((SMALLDELAY+BIGDELAY) * SPEED_BLINK_COUNT/2);
}
delay(100);
// ---------- effect #3 -----------
startPWM();
for(int i = 0; i < 500; i++) {
blueFlashLightIteration();
redFlashLightIteration();
delay(20);
}
stopPWM();
delay(100);
// ---------- effect #4 -----------
for (uint8_t j = 0; j < 7; j++) {
for(uint8_t i = 0; i < 5; i++) {
uint8_t counter = j * 5 + i;
uint8_t isRed = counter % 2;
PORTB = isRed ? RED : BLUE;
delay(BIGDELAY);
}
delay((SMALLDELAY + BIGDELAY) * 4);
}
delay(100);
}
}