summaryrefslogtreecommitdiffstats
path: root/fw/pwm.c
diff options
context:
space:
mode:
authorVäinö Kauppila <vaino@vke.fi>2026-04-19 19:02:42 +0300
committerVäinö Kauppila <vaino@vke.fi>2026-04-19 19:02:42 +0300
commit46e1210381106707c2df7f07c56023eb6b760763 (patch)
tree6740a17199f76e2965a511dafcbc7ffb61ceafeb /fw/pwm.c
parenteb8643ddbef43547eb7bfe58789a3908926c7258 (diff)
downloadvhdl_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.c53
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 */
+ }
+ }
+ }
+ }
+}