fix bad formattingfrom PR
[clinton/Smoothieware.git] / src / modules / tools / laser / Laser.cpp
index 87dda5e..117cd9e 100644 (file)
@@ -42,8 +42,9 @@
 Laser::Laser()
 {
     laser_on = false;
-    scale= 1;
-    manual_fire= false;
+    scale = 1;
+    manual_fire = false;
+    fire_duration = 0;
 }
 
 void Laser::on_module_loaded()
@@ -90,7 +91,7 @@ void Laser::on_module_loaded()
     }
 
 
-    uint32_t period= THEKERNEL->config->value(laser_module_pwm_period_checksum)->by_default(20)->as_number();
+    uint32_t period = THEKERNEL->config->value(laser_module_pwm_period_checksum)->by_default(20)->as_number();
     this->pwm_pin->period_us(period);
     this->pwm_pin->write(this->pwm_inverting ? 1 : 0);
     this->laser_maximum_power = THEKERNEL->config->value(laser_module_maximum_power_checksum)->by_default(1.0f)->as_number() ;
@@ -112,8 +113,9 @@ void Laser::on_module_loaded()
     this->register_for_event(ON_CONSOLE_LINE_RECEIVED);
     this->register_for_event(ON_GET_PUBLIC_DATA);
 
-    // no point in updating the power more than the PWM frequency, but no more than 1KHz
-    THEKERNEL->slow_ticker->attach(std::min(1000UL, 1000000/period), this, &Laser::set_proportional_power);
+    // no point in updating the power more than the PWM frequency, but not faster than 1KHz
+    ms_per_tick = 1000 / std::min(1000UL, 1000000 / period);
+    THEKERNEL->slow_ticker->attach(std::min(1000UL, 1000000 / period), this, &Laser::set_proportional_power);
 }
 
 void Laser::on_console_line_received( void *argument )
@@ -134,23 +136,42 @@ void Laser::on_console_line_received( void *argument )
     if (cmd == "fire") {
         string power = shift_parameter(possible_command);
         if(power.empty()) {
-            msgp->stream->printf("Usage: fire power%%|off\n");
+            msgp->stream->printf("Usage: fire power%% [durationms]|off|status\n");
             return;
         }
 
         float p;
+        fire_duration = 0; // By default unlimited
+        if(power == "status") {
+            msgp->stream->printf("laser manual state: %s\n", manual_fire ? "on" : "off");
+            return;
+        }
         if(power == "off" || power == "0") {
-            p= 0;
+            p = 0;
             msgp->stream->printf("turning laser off and returning to auto mode\n");
-
-        }else{
-            p= strtof(power.c_str(), NULL);
-            p= confine(p, 0.0F, 100.0F);
-            msgp->stream->printf("WARNING: Firing laser at %1.2f%% power, entering manual mode use fire off to return to auto mode\n", p);
+        } else {
+            p = strtof(power.c_str(), NULL);
+            p = confine(p, 0.0F, 100.0F);
+            string duration = shift_parameter(possible_command);
+            if(!duration.empty()) {
+                fire_duration = atoi(duration.c_str());
+                // Avoid negative values, its just incorrect
+                if (fire_duration < ms_per_tick) {
+                    msgp->stream->printf("WARNING: Minimal duration is %ld ms, not firing\n", ms_per_tick);
+                    return;
+                }
+                // rounding to minimal value
+                if (fire_duration % ms_per_tick != 0) {
+                    fire_duration = (fire_duration / ms_per_tick) * ms_per_tick;
+                }
+                msgp->stream->printf("WARNING: Firing laser at %1.2f%% power, for %ld ms, use fire off to stop test fire earlier\n", p, fire_duration);
+            } else {
+                msgp->stream->printf("WARNING: Firing laser at %1.2f%% power, entering manual mode use fire off to return to auto mode\n", p);
+            }
         }
 
-        p= p/100.0F;
-        manual_fire= set_laser_power(p);
+        p = p / 100.0F;
+        manual_fire = set_laser_power(p);
     }
 }
 
@@ -173,7 +194,7 @@ void Laser::on_gcode_received(void *argument)
     if (gcode->has_m) {
         if (gcode->m == 221) { // M221 S100 change laser power by percentage S
             if(gcode->has_letter('S')) {
-                this->scale= gcode->get_value('S') / 100.0F;
+                this->scale = gcode->get_value('S') / 100.0F;
 
             } else {
                 gcode->stream->printf("Laser power scale at %6.2f %%\n", this->scale * 100.0F);
@@ -186,19 +207,19 @@ void Laser::on_gcode_received(void *argument)
 float Laser::current_speed_ratio(const Block *block) const
 {
     // find the primary moving actuator (the one with the most steps)
-    size_t pm= 0;
-    uint32_t max_steps= 0;
+    size_t pm = 0;
+    uint32_t max_steps = 0;
     for (size_t i = 0; i < THEROBOT->get_number_registered_motors(); i++) {
         // find the motor with the most steps
         if(block->steps[i] > max_steps) {
-            max_steps= block->steps[i];
-            pm= i;
+            max_steps = block->steps[i];
+            pm = i;
         }
     }
 
     // figure out the ratio of its speed, from 0 to 1 based on where it is on the trapezoid,
     // this is based on the fraction it is of the requested rate (nominal rate)
-    float ratio= block->get_trapezoid_rate(pm) / block->nominal_rate;
+    float ratio = block->get_trapezoid_rate(pm) / block->nominal_rate;
 
     return ratio;
 }
@@ -211,7 +232,7 @@ bool Laser::get_laser_power(float& power) const
     // Note to avoid a race condition where the block is being cleared we check the is_ready flag which gets cleared first,
     // as this is an interrupt if that flag is not clear then it cannot be cleared while this is running and the block will still be valid (albeit it may have finished)
     if(block != nullptr && block->is_ready && block->is_g123) {
-        float requested_power = ((float)block->s_value/(1<<11)) / this->laser_maximum_s_value; // s_value is 1.11 Fixed point
+        float requested_power = ((float)block->s_value / (1 << 11)) / this->laser_maximum_s_value; // s_value is 1.11 Fixed point
         float ratio = current_speed_ratio(block);
         power = requested_power * ratio * scale;
 
@@ -224,7 +245,19 @@ bool Laser::get_laser_power(float& power) const
 // called every millisecond from timer ISR
 uint32_t Laser::set_proportional_power(uint32_t dummy)
 {
-    if(manual_fire) return 0;
+    if(manual_fire) {
+        // If we have fire duration set
+        if (fire_duration) {
+            // Decrease it each ms
+            fire_duration -= ms_per_tick;
+            // And if it turned 0, disable laser and manual fire mode
+            if (fire_duration <= 0) {
+                set_laser_power(0);
+                manual_fire = false;
+            }
+        }
+        return 0;
+    }
 
     float power;
     if(get_laser_power(power)) {
@@ -242,14 +275,14 @@ uint32_t Laser::set_proportional_power(uint32_t dummy)
 bool Laser::set_laser_power(float power)
 {
     // Ensure power is >=0 and <= 1
-    power= confine(power, 0.0F, 1.0F);
+    power = confine(power, 0.0F, 1.0F);
 
     if(power > 0.00001F) {
         this->pwm_pin->write(this->pwm_inverting ? 1 - power : power);
         if(!laser_on && this->ttl_used) this->ttl_pin->set(true);
         laser_on = true;
 
-    }else{
+    } else {
         this->pwm_pin->write(this->pwm_inverting ? 1 : 0);
         if (this->ttl_used) this->ttl_pin->set(false);
         laser_on = false;
@@ -262,11 +295,12 @@ void Laser::on_halt(void *argument)
 {
     if(argument == nullptr) {
         set_laser_power(0);
-        manual_fire= false;
+        manual_fire = false;
     }
 }
 
 float Laser::get_current_power() const
 {
-    return pwm_pin->read() * 100;
+    float p = pwm_pin->read();
+    return (this->pwm_inverting ? 1 - p : p) * 100;
 }