From d320545066676338d4a0142268931bb66eedfccc Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Tue, 8 Jun 2021 07:51:28 -0500
Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Laser=20Ammeter=20followup=20(#2?=
 =?UTF-8?q?2079)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Followup to #21835
---
 Marlin/Configuration_adv.h                  | 21 ++++----
 Marlin/src/HAL/STM32/eeprom_flash.cpp       |  2 +-
 Marlin/src/feature/ammeter.cpp              | 43 ++++++++-------
 Marlin/src/feature/ammeter.h                | 13 ++---
 Marlin/src/feature/spindle_laser.cpp        |  3 +-
 Marlin/src/inc/Conditionals_LCD.h           |  4 ++
 Marlin/src/lcd/HD44780/marlinui_HD44780.cpp | 31 ++++-------
 Marlin/src/lcd/dogm/dogm_Statusscreen.h     | 60 ++++++++++-----------
 Marlin/src/lcd/dogm/status/ammeter.h        | 11 ++--
 Marlin/src/lcd/dogm/status_screen_DOGM.cpp  |  4 +-
 Marlin/src/libs/numtostr.cpp                |  9 ----
 Marlin/src/libs/numtostr.h                  |  3 --
 buildroot/tests/mega2560                    |  2 +-
 13 files changed, 90 insertions(+), 116 deletions(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 50bc85801f3..5bd3c516031 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -3283,15 +3283,6 @@
     //#define AIR_ASSIST_PIN            44     // Override the default Air Assist pin
   #endif
 
-  //
-  // Laser I2C Ammeter (High precision INA226 low/high side module)
-  //
-  //#define I2C_AMMETER
-  #if ENABLED(I2C_AMMETER)
-    #define I2C_AMMETER_IMAX            .1     // Calibration value for the expected current range in Amps (use float e.g. 1.0)
-    #define I2C_AMMETER_SHUNT_RESISTOR  .1     // Calibration shunt resistor value in ohms
-  #endif
-
   //#define SPINDLE_SERVO                      // A servo converting an angle to spindle power
   #ifdef SPINDLE_SERVO
     #define SPINDLE_SERVO_NR   0               // Index of servo used for spindle control
@@ -3424,8 +3415,18 @@
       #define SPINDLE_LASER_POWERDOWN_DELAY   50 // (ms) Delay to allow the spindle to stop
 
     #endif
+
+    //
+    // Laser I2C Ammeter (High precision INA226 low/high side module)
+    //
+    //#define I2C_AMMETER
+    #if ENABLED(I2C_AMMETER)
+      #define I2C_AMMETER_IMAX            0.1    // (Amps) Calibration value for the expected current range
+      #define I2C_AMMETER_SHUNT_RESISTOR  0.1    // (Ohms) Calibration shunt resistor value
+    #endif
+
   #endif
-#endif
+#endif // SPINDLE_FEATURE || LASER_FEATURE
 
 /**
  * Synchronous Laser Control with M106/M107
diff --git a/Marlin/src/HAL/STM32/eeprom_flash.cpp b/Marlin/src/HAL/STM32/eeprom_flash.cpp
index 3d06b172bd7..dfeae9e9e5e 100644
--- a/Marlin/src/HAL/STM32/eeprom_flash.cpp
+++ b/Marlin/src/HAL/STM32/eeprom_flash.cpp
@@ -30,7 +30,7 @@
 
 // Better: "utility/stm32_eeprom.h", but only after updating stm32duino to 2.0.0
 // Use EEPROM.h for compatibility, for now.
-#include <EEPROM.h> 
+#include <EEPROM.h>
 
 /**
  * The STM32 HAL supports chips that deal with "pages" and some with "sectors" and some that
diff --git a/Marlin/src/feature/ammeter.cpp b/Marlin/src/feature/ammeter.cpp
index 01e10844748..71b84f1121a 100644
--- a/Marlin/src/feature/ammeter.cpp
+++ b/Marlin/src/feature/ammeter.cpp
@@ -1,4 +1,4 @@
-  /**
+/**
  * Marlin 3D Printer Firmware
  * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  *
@@ -23,27 +23,32 @@
 #include "../inc/MarlinConfig.h"
 
 #if ENABLED(I2C_AMMETER)
-  #include "ammeter.h"
 
-  INA226 ina;
+#include "ammeter.h"
 
-  Ammeter ammeter;
+#ifndef I2C_AMMETER_IMAX
+  #define I2C_AMMETER_IMAX     0.500  // Calibration range 500 Milliamps
+#endif
 
-  float Ammeter::scale;
-  float Ammeter::current;
+INA226 ina;
 
-  void Ammeter::init() {
-    ina.begin();
-    ina.configure(INA226_AVERAGES_16, INA226_BUS_CONV_TIME_1100US, INA226_SHUNT_CONV_TIME_1100US, INA226_MODE_SHUNT_BUS_CONT);
-    ina.calibrate(I2C_AMMETER_SHUNT_RESISTOR,I2C_AMMETER_IMAX);
-  }
+Ammeter ammeter;
 
-  float Ammeter::read() {
-      scale = 1;
-      current = ina.readShuntCurrent();
-      if (current <= .0001) current = 0;  // Cleanup lsb bit amplification errors
-      if (current < .1) scale = 1000; 
-      return current * scale;
-  }
+float Ammeter::scale;
+float Ammeter::current;
 
-#endif //I2C_AMMETER
+void Ammeter::init() {
+  ina.begin();
+  ina.configure(INA226_AVERAGES_16, INA226_BUS_CONV_TIME_1100US, INA226_SHUNT_CONV_TIME_1100US, INA226_MODE_SHUNT_BUS_CONT);
+  ina.calibrate(I2C_AMMETER_SHUNT_RESISTOR, I2C_AMMETER_IMAX);
+}
+
+float Ammeter::read() {
+  scale = 1;
+  current = ina.readShuntCurrent();
+  if (current <= 0.0001f) current = 0;  // Clean up least-significant-bit amplification errors
+  if (current < 0.1f) scale = 1000;
+  return current * scale;
+}
+
+#endif // I2C_AMMETER
diff --git a/Marlin/src/feature/ammeter.h b/Marlin/src/feature/ammeter.h
index cc60a2d28ae..86f09bb9a19 100644
--- a/Marlin/src/feature/ammeter.h
+++ b/Marlin/src/feature/ammeter.h
@@ -26,19 +26,14 @@
 #include <Wire.h>
 #include <INA226.h>
 
-#ifndef I2C_AMMETER_IMAX    
-  #define I2C_AMMETER_IMAX      .500 // Calibration range 500 Milli Amps
-#endif
-
 class Ammeter {
 private:
-    static float scale;
+  static float scale;
 
 public:
-    static float current;
-    static void init();
-    static float read();
- 
+  static float current;
+  static void init();
+  static float read();
 };
 
 extern Ammeter ammeter;
diff --git a/Marlin/src/feature/spindle_laser.cpp b/Marlin/src/feature/spindle_laser.cpp
index 58dc5ef101c..539fafeb349 100644
--- a/Marlin/src/feature/spindle_laser.cpp
+++ b/Marlin/src/feature/spindle_laser.cpp
@@ -79,9 +79,8 @@ void SpindleLaser::init() {
     OUT_WRITE(AIR_ASSIST_PIN, !AIR_ASSIST_ACTIVE);                    // Init Air Assist OFF
   #endif
   #if ENABLED(I2C_AMMETER)
-    ammeter.init();                    // Init I2C Ammeter
+    ammeter.init();                                                   // Init I2C Ammeter
   #endif
-  
 }
 
 #if ENABLED(SPINDLE_LASER_PWM)
diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h
index d66ceabc19a..9e87589ca8d 100644
--- a/Marlin/src/inc/Conditionals_LCD.h
+++ b/Marlin/src/inc/Conditionals_LCD.h
@@ -405,6 +405,10 @@
 
 #endif
 
+#if EITHER(LCD_I2C_TYPE_MCP23017, LCD_I2C_TYPE_MCP23008) && DISABLED(NO_LCD_DETECT)
+  #define DETECT_I2C_LCD_DEVICE 1
+#endif
+
 #ifndef STD_ENCODER_PULSES_PER_STEP
   #if ENABLED(TOUCH_SCREEN)
     #define STD_ENCODER_PULSES_PER_STEP 2
diff --git a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp
index ab3d415c15f..0c87c3dc3fa 100644
--- a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp
+++ b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp
@@ -68,11 +68,7 @@
 
 #elif EITHER(LCD_I2C_TYPE_MCP23017, LCD_I2C_TYPE_MCP23008)
 
-  LCD_CLASS lcd(LCD_I2C_ADDRESS
-    #ifdef DETECT_DEVICE
-      , 1
-    #endif
-  );
+  LCD_CLASS lcd(LCD_I2C_ADDRESS OPTARG(DETECT_I2C_LCD_DEVICE, 1));
 
 #elif ENABLED(LCD_I2C_TYPE_PCA8574)
 
@@ -380,11 +376,7 @@ void MarlinUI::init_lcd() {
 }
 
 bool MarlinUI::detected() {
-  return (true
-    #if EITHER(LCD_I2C_TYPE_MCP23017, LCD_I2C_TYPE_MCP23008) && defined(DETECT_DEVICE)
-      && lcd.LcdDetected() == 1
-    #endif
-  );
+  return TERN1(DETECT_I2C_LCD_DEVICE, lcd.LcdDetected() == 1);
 }
 
 #if HAS_SLOW_BUTTONS
@@ -602,10 +594,11 @@ FORCE_INLINE void _draw_cooler_status(const char prefix, const bool blink) {
   FORCE_INLINE void _draw_ammeter_status() {
     lcd_put_u8str(" ");
     ammeter.read();
-    if (ammeter.current <= .999) {
-      lcd_put_u8str(ftostr3ns(ammeter.current));
+    if (ammeter.current <= 0.999f) {
+      lcd_put_u8str(ui16tostr3rj(uint16_t(ammeter.current * 1000 + 0.5f)));
       lcd_put_u8str("mA");
-    } else {
+    }
+    else {
       lcd_put_u8str(ftostr12ns(ammeter.current));
       lcd_put_wchar('A');
     }
@@ -847,15 +840,9 @@ void MarlinUI::draw_status_screen() {
         #endif
       #endif
 
-      #if HAS_COOLER
-        _draw_cooler_status('*', blink);
-      #endif
-      #if ENABLED(LASER_COOLANT_FLOW_METER)
-        _draw_flowmeter_status();
-      #endif
-      #if ENABLED(I2C_AMMETER)
-        _draw_ammeter_status();
-      #endif
+      TERN_(HAS_COOLER, _draw_cooler_status('*', blink));
+      TERN_(LASER_COOLANT_FLOW_METER, _draw_flowmeter_status());
+      TERN_(I2C_AMMETER, _draw_ammeter_status());
 
     #endif // LCD_WIDTH >= 20
 
diff --git a/Marlin/src/lcd/dogm/dogm_Statusscreen.h b/Marlin/src/lcd/dogm/dogm_Statusscreen.h
index db0b66777da..6aa2bab0da9 100644
--- a/Marlin/src/lcd/dogm/dogm_Statusscreen.h
+++ b/Marlin/src/lcd/dogm/dogm_Statusscreen.h
@@ -110,14 +110,13 @@
 //
 // Laser Ammeter
 //
-#if !STATUS_AMMETER_WIDTH && ENABLED(I2C_AMMETER)
-  #include "status/ammeter.h"
-#endif
-#ifndef STATUS_AMMETER_WIDTH
-  #define STATUS_AMMETER_WIDTH 0
-#endif
-#ifndef STATUS_AMMETER_BYTEWIDTH
-  #define STATUS_AMMETER_BYTEWIDTH BW(STATUS_AMMETER_WIDTH)
+#if ENABLED(I2C_AMMETER)
+  #if !STATUS_AMMETER_WIDTH
+    #include "status/ammeter.h"
+  #endif
+  #ifndef STATUS_AMMETER_WIDTH
+    #define STATUS_AMMETER_WIDTH 0
+  #endif
 #endif
 
 //
@@ -614,30 +613,29 @@
   #endif
 #endif
 
-#if ENABLED(I2C_AMMETER)
-  #if STATUS_AMMETER_WIDTH
-
-    #ifndef STATUS_AMMETER_X
-      #define STATUS_AMMETER_X (LCD_PIXEL_WIDTH - (STATUS_AMMETER_BYTEWIDTH + STATUS_FLOWMETER_BYTEWIDTH + STATUS_FAN_BYTEWIDTH + STATUS_CUTTER_BYTEWIDTH + STATUS_COOLER_BYTEWIDTH) * 8)
-    #endif
-
-    #ifndef STATUS_AMMETER_HEIGHT
-      #define STATUS_AMMETER_HEIGHT(S) (sizeof(status_ammeter_bmp1) / (STATUS_AMMETER_BYTEWIDTH))
-    #endif
-
-    #ifndef STATUS_AMMETER_Y
-      #define STATUS_AMMETER_Y(S) (18 - STATUS_AMMETER_HEIGHT(S))
-    #endif
-
-    #ifndef STATUS_AMMETER_TEXT_X
-      #define STATUS_AMMETER_TEXT_X (STATUS_AMMETER_X + 7)
-    #endif
-
-    static_assert(
-      sizeof(status_ammeter_bmp1) == (STATUS_AMMETER_BYTEWIDTH) * STATUS_AMMETER_HEIGHT(0),
-      "Status ammeter bitmap (status_ammeter_bmp1) dimensions don't match data."
-    );
+//
+// I2C Laser Ammeter
+//
+#if ENABLED(I2C_AMMETER) && STATUS_AMMETER_WIDTH
+  #ifndef STATUS_AMMETER_BYTEWIDTH
+    #define STATUS_AMMETER_BYTEWIDTH BW(STATUS_AMMETER_WIDTH)
   #endif
+  #ifndef STATUS_AMMETER_X
+    #define STATUS_AMMETER_X (LCD_PIXEL_WIDTH - (STATUS_AMMETER_BYTEWIDTH + STATUS_FLOWMETER_BYTEWIDTH + STATUS_FAN_BYTEWIDTH + STATUS_CUTTER_BYTEWIDTH + STATUS_COOLER_BYTEWIDTH) * 8)
+  #endif
+  #ifndef STATUS_AMMETER_HEIGHT
+    #define STATUS_AMMETER_HEIGHT(S) (sizeof(status_ammeter_bmp1) / (STATUS_AMMETER_BYTEWIDTH))
+  #endif
+  #ifndef STATUS_AMMETER_Y
+    #define STATUS_AMMETER_Y(S) (18 - STATUS_AMMETER_HEIGHT(S))
+  #endif
+  #ifndef STATUS_AMMETER_TEXT_X
+    #define STATUS_AMMETER_TEXT_X (STATUS_AMMETER_X + 7)
+  #endif
+  static_assert(
+    sizeof(status_ammeter_bmp1) == (STATUS_AMMETER_BYTEWIDTH) * STATUS_AMMETER_HEIGHT(0),
+    "Status ammeter bitmap (status_ammeter_bmp1) dimensions don't match data."
+  );
 #endif
 
 //
diff --git a/Marlin/src/lcd/dogm/status/ammeter.h b/Marlin/src/lcd/dogm/status/ammeter.h
index c98d1eb4013..d99ea6949a6 100644
--- a/Marlin/src/lcd/dogm/status/ammeter.h
+++ b/Marlin/src/lcd/dogm/status/ammeter.h
@@ -1,6 +1,6 @@
 /**
  * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  *
  * Based on Sprinter and grbl.
  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
@@ -24,11 +24,10 @@
 //
 // lcd/dogm/status/ammeter.h - Status Screen Laser Ammeter bitmaps
 //
-#if ENABLED(I2C_AMMETER)
 
-  #define STATUS_AMMETER_WIDTH 20
+#define STATUS_AMMETER_WIDTH 20
 
-  const unsigned char status_ammeter_bmp_mA[] PROGMEM = {
+const unsigned char status_ammeter_bmp_mA[] PROGMEM = {
   B00000000,B11111100,B00000000,
   B00000011,B00000011,B00000000,
   B00000100,B00000000,B10000000,
@@ -46,7 +45,7 @@
   B00000100,B00000000,B10000000,
   B00000011,B00000011,B00000000,
   B00000000,B11111100,B00000000
-  };
+};
 
 const unsigned char status_ammeter_bmp_A[] PROGMEM = {
   B00000000,B11111100,B00000000,
@@ -67,5 +66,3 @@ const unsigned char status_ammeter_bmp_A[] PROGMEM = {
   B00000011,B00000011,B00000000,
   B00000000,B11111100,B00000000,
 };
-
-#endif
diff --git a/Marlin/src/lcd/dogm/status_screen_DOGM.cpp b/Marlin/src/lcd/dogm/status_screen_DOGM.cpp
index 00e8af66e22..8309c3a00e8 100644
--- a/Marlin/src/lcd/dogm/status_screen_DOGM.cpp
+++ b/Marlin/src/lcd/dogm/status_screen_DOGM.cpp
@@ -207,7 +207,7 @@ FORCE_INLINE void _draw_centered_temp(const celsius_t temp, const uint8_t tx, co
 
 #if DO_DRAW_AMMETER
   FORCE_INLINE void _draw_centered_current(const float current, const uint8_t tx, const uint8_t ty) {
-    const char *str = ftostr31ns(current);           
+    const char *str = ftostr31ns(current);
     const uint8_t len = str[0] != ' ' ? 3 : str[1] != ' ' ? 2 : 1;
     lcd_put_u8str(tx - len * (INFO_FONT_WIDTH) / 2 + 1, ty, &str[3-len]);
   }
@@ -697,7 +697,7 @@ void MarlinUI::draw_status_screen() {
       const uint8_t ammetery = STATUS_AMMETER_Y(status_ammeter_bmp_mA),
                     ammeterh = STATUS_AMMETER_HEIGHT(status_ammeter_bmp_mA);
        if (PAGE_CONTAINS(ammetery, ammetery + ammeterh - 1))
-        u8g.drawBitmapP(STATUS_AMMETER_X, ammetery, STATUS_AMMETER_BYTEWIDTH, ammeterh, (ammeter.current < .1) ? status_ammeter_bmp_mA : status_ammeter_bmp_A);
+        u8g.drawBitmapP(STATUS_AMMETER_X, ammetery, STATUS_AMMETER_BYTEWIDTH, ammeterh, (ammeter.current < 0.1f) ? status_ammeter_bmp_mA : status_ammeter_bmp_A);
     #endif
 
     // Heated Bed
diff --git a/Marlin/src/libs/numtostr.cpp b/Marlin/src/libs/numtostr.cpp
index a1e320844ad..1e1ac057101 100644
--- a/Marlin/src/libs/numtostr.cpp
+++ b/Marlin/src/libs/numtostr.cpp
@@ -217,15 +217,6 @@ const char* ftostr41ns(const_float_t f) {
   return &conv[2];
 }
 
-// Convert unsigned float to string with 123 format
-const char* ftostr3ns(const_float_t f) {
-  const long i = UINTFLOAT(f, 3);
-  conv[4] = DIGIMOD(i, 100);
-  conv[5] = DIGIMOD(i, 10);
-  conv[6] = DIGIMOD(i, 1);
-  return &conv[4];
-}
-
 // Convert signed float to fixed-length string with 12.34 / _2.34 / -2.34 or -23.45 / 123.45 format
 const char* ftostr42_52(const_float_t f) {
   if (f <= -10 || f >= 100) return ftostr52(f); // -23.45 / 123.45
diff --git a/Marlin/src/libs/numtostr.h b/Marlin/src/libs/numtostr.h
index 5ebf6e1b221..b058f3cdf6c 100644
--- a/Marlin/src/libs/numtostr.h
+++ b/Marlin/src/libs/numtostr.h
@@ -74,9 +74,6 @@ const char* ftostr31ns(const_float_t x);
 // Convert unsigned float to string with 123.4 format
 const char* ftostr41ns(const_float_t x);
 
-// Convert unsigned float to string with 123 format
-const char* ftostr3ns(const_float_t x);
-
 // Convert signed float to fixed-length string with 12.34 / _2.34 / -2.34 or -23.45 / 123.45 format
 const char* ftostr42_52(const_float_t x);
 
diff --git a/buildroot/tests/mega2560 b/buildroot/tests/mega2560
index ecf82267f49..3ddb68fe883 100755
--- a/buildroot/tests/mega2560
+++ b/buildroot/tests/mega2560
@@ -193,7 +193,7 @@ opt_set MOTHERBOARD BOARD_RAMPS_14_EFB EXTRUDERS 0 LCD_LANGUAGE en TEMP_SENSOR_C
         MANUAL_FEEDRATE '{ 50*60, 50*60, 4*60 }' \
         AXIS_RELATIVE_MODES '{ false, false, false }'
 opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \
-           LASER_FEATURE AIR_EVACUATION AIR_EVACUATION_PIN AIR_ASSIST AIR_ASSIST_PIN LASER_COOLANT_FLOW_METER
+           LASER_FEATURE AIR_EVACUATION AIR_EVACUATION_PIN AIR_ASSIST AIR_ASSIST_PIN LASER_COOLANT_FLOW_METER I2C_AMMETER
 
 exec_test $1 $2 "REPRAP MEGA2560 RAMPS | Laser Feature | Air Evacuation | Air Assist | Cooler | Flowmeter | 44780 LCD " "$3"