From 7481563bd98b43b2add28ac912b12043b1c2ef94 Mon Sep 17 00:00:00 2001
From: gjdodd <31553294+gjdodd@users.noreply.github.com>
Date: Wed, 15 Jan 2020 23:59:41 +0000
Subject: [PATCH] Nikon IR support for time lapse photos (#16539)

---
 Marlin/Configuration_adv.h               | 16 ++++++++-
 Marlin/src/gcode/feature/camera/M240.cpp | 43 +++++++++++++++++++++---
 2 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 4685198fc2..ec2e995e94 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -368,7 +368,7 @@
  * FAST_PWM_FAN_FREQUENCY [undefined by default]
  *   Set this to your desired frequency.
  *   If left undefined this defaults to F = F_CPU/(2*255*1)
- *   ie F = 31.4 Khz on 16 MHz microcontrollers or F = 39.2 KHz on 20 MHz microcontrollers
+ *   i.e., F = 31.4kHz on 16MHz microcontrollers or F = 39.2kHz on 20MHz microcontrollers.
  *   These defaults are the same as with the old FAST_PWM_FAN implementation - no migration is required
  *   NOTE: Setting very low frequencies (< 10 Hz) may result in unexpected timer behavior.
  *
@@ -2444,6 +2444,20 @@
 
   // Duration to hold the switch or keep CHDK_PIN high
   //#define PHOTO_SWITCH_MS   50 // (ms) (M240 D)
+
+  /**
+   * PHOTO_PULSES_US may need adjustment depending on board and camera model.
+   * Pin must be running at 48.4kHz.
+   * Be sure to use a PHOTOGRAPH_PIN which can rise and fall quick enough.
+   * (e.g., MKS SBase temp sensor pin was too slow, so used P1.23 on J8.)
+   *
+   *  Example pulse data for Nikon: https://bit.ly/2FKD0Aq
+   *                     IR Wiring: https://git.io/JvJf7
+   */
+  //#define PHOTO_PULSES_US { 2000, 27850, 400, 1580, 400, 3580, 400 }  // (µs) Durations for each 48.4kHz oscillation
+  #ifdef PHOTO_PULSES_US
+    #define PHOTO_PULSE_DELAY_US 13 // (µs) Approximate duration of each HIGH and LOW pulse in the oscillation
+  #endif
 #endif
 
 /**
diff --git a/Marlin/src/gcode/feature/camera/M240.cpp b/Marlin/src/gcode/feature/camera/M240.cpp
index 46ee958ebd..147dfccf05 100644
--- a/Marlin/src/gcode/feature/camera/M240.cpp
+++ b/Marlin/src/gcode/feature/camera/M240.cpp
@@ -62,11 +62,44 @@
 #endif
 
 #if PIN_EXISTS(PHOTOGRAPH)
-  constexpr uint8_t NUM_PULSES = 16;
-  constexpr float PULSE_LENGTH = 0.01524;
-  inline void set_photo_pin(const uint8_t state) { WRITE(PHOTOGRAPH_PIN, state); _delay_ms(PULSE_LENGTH); }
-  inline void tweak_photo_pin() { set_photo_pin(HIGH); set_photo_pin(LOW); }
-  inline void spin_photo_pin() { for (uint8_t i = NUM_PULSES; i--;) tweak_photo_pin(); }
+
+  FORCE_INLINE void set_photo_pin(const uint8_t state) {
+    constexpr uint32_t pulse_length = (
+      #ifdef PHOTO_PULSES_US
+        PHOTO_PULSE_DELAY_US
+      #else
+        15                    // 15.24 from _delay_ms(0.01524)
+      #endif
+    );
+    WRITE(PHOTOGRAPH_PIN, state);
+    delayMicroseconds(pulse_length);
+  }
+
+  FORCE_INLINE void tweak_photo_pin() { set_photo_pin(HIGH); set_photo_pin(LOW); }
+
+  #ifdef PHOTO_PULSES_US
+
+    inline void pulse_photo_pin(const uint32_t duration, const uint8_t state) {
+      if (state) {
+        for (const uint32_t stop = micros() + duration; micros() < stop;)
+          tweak_photo_pin();
+      }
+      else
+        delayMicroseconds(duration);
+    }
+
+    inline void spin_photo_pin() {
+      static constexpr uint32_t sequence[] = PHOTO_PULSES_US;
+      for (uint8_t i = 0; i < COUNT(sequence); i++)
+        pulse_photo_pin(sequence[i], !(i & 1));
+    }
+
+  #else
+
+    constexpr uint8_t NUM_PULSES = 16;
+    inline void spin_photo_pin() { for (uint8_t i = NUM_PULSES; i--;) tweak_photo_pin(); }
+
+  #endif
 #endif
 
 /**
-- 
GitLab