diff options
| author | Väinö Kauppila <vaino@vke.fi> | 2026-04-19 19:02:42 +0300 |
|---|---|---|
| committer | Väinö Kauppila <vaino@vke.fi> | 2026-04-19 19:02:42 +0300 |
| commit | 46e1210381106707c2df7f07c56023eb6b760763 (patch) | |
| tree | 6740a17199f76e2965a511dafcbc7ffb61ceafeb /fw/pwm.c | |
| parent | eb8643ddbef43547eb7bfe58789a3908926c7258 (diff) | |
| download | vhdl_pic-46e1210381106707c2df7f07c56023eb6b760763.tar.gz vhdl_pic-46e1210381106707c2df7f07c56023eb6b760763.zip | |
BSRAM progmem. fix Makefile memory command that does not work. add interrupts, bank 1, timer0. Timer0 not tested.
Diffstat (limited to 'fw/pwm.c')
| -rw-r--r-- | fw/pwm.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/fw/pwm.c b/fw/pwm.c new file mode 100644 index 0000000..60f8b5c --- /dev/null +++ b/fw/pwm.c @@ -0,0 +1,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 */ + } + } + } + } +} |
