Implemented a 'breathe' style pulse pattern for the PWM LED.
authorPat Thoyts <patthoyts@users.sourceforge.net>
Wed, 12 Aug 2015 23:15:53 +0000 (00:15 +0100)
committerPat Thoyts <patthoyts@users.sourceforge.net>
Wed, 12 Aug 2015 23:15:53 +0000 (00:15 +0100)
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
timer-demo.c

index 83fe5e64b46b41cbb2ce61a8476de240d8680b52..4824a89c028b14969f03b90611541ce72df600d7 100644 (file)
@@ -15,6 +15,9 @@
 #include <avr/wdt.h>
 #include <util/delay.h>
 
+static void init_timer2(void);
+static void init_pwm_pin9(void);
+
 /*
  * timer2:
  * Using a /64 prescaler with 1 16MHz clock and counting from
@@ -34,22 +37,56 @@ const uint8_t TIMER_INIT = 6;
 const uint16_t PWM_TOP = 212;
 const uint16_t PWM_MATCH = 212/2; /* square wave, 50% */
 
+/*
+ * "breathe" pattern to match Apple's sleep indicator.
+ * Should use 100-200 Hz PWM, from 0 to 25% duty over a 1.7s period
+ * generated using exp(sin(x))
+ */
+const uint8_t Pattern[255] PROGMEM = {
+  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3,
+  4, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 12, 13, 13, 14, 15,
+  16, 17, 19, 20, 21, 22, 23, 25, 26, 28, 29, 31, 32, 34,
+  36, 37, 39, 41, 43, 45, 47, 49, 51, 53, 56, 58, 61, 63, 66,
+  68, 71, 74, 77, 79, 82, 85, 88, 92, 95, 98, 101, 105, 108, 112,
+  115, 119, 122, 126, 130, 134, 137, 141, 145, 149, 153, 157, 160,
+  164, 168, 172, 176, 180, 184, 187, 191, 195, 198, 202, 205, 209,
+  212, 215, 219, 222, 225, 227, 230, 233, 235, 238, 240, 242, 244,
+  246, 247, 249, 250, 251, 252, 253, 253, 254, 254, 254, 254, 253,
+  253, 252, 251, 250, 249, 248, 246, 245, 243, 241, 239, 236, 234,
+  232, 229, 226, 223, 220, 217, 214, 211, 207, 204, 200, 197, 193,
+  189, 185, 182, 178, 174, 170, 166, 162, 159, 155, 151, 147, 143,
+  139, 135, 132, 128, 124, 121, 117, 113, 110, 107, 103, 100, 96,
+  93, 90, 87, 84, 81, 78, 75, 72, 70, 67, 64, 62, 59, 57, 55, 52,
+  50, 48, 46, 44, 42, 40, 38, 36, 35, 33, 31, 30, 28, 27, 25, 24,
+  23, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 10, 9, 8, 8,
+  7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0
+};
+
 volatile uint16_t counter = 0;
+volatile uint8_t pulse_delay = 0, pulse_index = 0;
 
 ISR(TIMER2_OVF_vect)
 {
     cli();
     TCNT2 = TIMER_INIT; /* reset the timer */
+
+    if (++pulse_delay == 7)
+    {
+        int v;
+        ++pulse_index;
+        v = (int)(uint8_t)pgm_read_byte_near(Pattern + pulse_index);
+        OCR1A = (v * PWM_TOP) / 256; /* table value scaled to PWM_TOP range */
+        pulse_delay = 0;
+    }
     if (++counter >= 250)
     {
         PORTD ^= _BV(PD5);
-        OCR1A = (OCR1A == 0) ? PWM_MATCH : 0;
         counter = 0;
     }
     sei();
 }
 
-static void init_timer2()
+static void init_timer2(void)
 {
     cli();
     /* 18.9: Disable the timer2 overflow interrupt for configuration */
@@ -69,7 +106,7 @@ static void init_timer2()
     sei();
 }
 
-static void init_pwm_pin9()
+static void init_pwm_pin9(void)
 {
     /* 
      *  PD5,PD6 (5,6) are attached to timer0 (8 bit)