blob: 60f8b5cf7b69090fc67097a5723e50566894547e (
plain) (
blame)
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
|
#include <pic16f84a.h>
typedef unsigned char uint8_t;
/*
* Breathing LED via bit-bang PWM on PORTA(0) and PORTB(0).
*
* The PWM period is 256 counts of the inner counter 'pwm'.
* Each duty level is held for HOLD_PERIODS full PWM periods before
* stepping, giving a smooth fade up then down (heartbeat pattern).
*
* At 50 MHz with SDCC's output (~10 instructions/iteration) the inner
* loop runs at roughly 5 MHz, so one 256-count PWM period ≈ 51 µs
* → ~20 kHz PWM. With HOLD_PERIODS = 32 each brightness step lasts
* ~1.6 ms and the full 0→255→0 sweep takes ~820 ms — a natural breath.
* Tweak HOLD_PERIODS to taste.
*/
#define HOLD_PERIODS 32
void main(void) {
uint8_t duty = 0; /* current duty cycle, 0..255 */
uint8_t dir = 1; /* 1 = ramping up, 0 = ramping down */
uint8_t pwm = 0; /* free-running counter within one period */
uint8_t periods = 0; /* how many full periods at this duty level */
while (1) {
/* PWM compare: LED on when we're inside the duty window */
if (pwm < duty) {
PORTA = 0x01;
PORTB = 0x01;
} else {
PORTA = 0x00;
PORTB = 0x00;
}
pwm++; /* wraps 255→0, completing one 256-count PWM period */
if (pwm == 0) {
periods++;
if (periods == HOLD_PERIODS) {
periods = 0;
if (dir) {
duty++;
if (duty == 255) dir = 0; /* peak: start ramping down */
} else {
duty--;
if (duty == 0) dir = 1; /* floor: start ramping up */
}
}
}
}
}
|