Add laser menu
authorJim Morris <morris@wolfman.com>
Tue, 13 Sep 2016 06:20:20 +0000 (23:20 -0700)
committerJim Morris <morris@wolfman.com>
Tue, 13 Sep 2016 06:20:20 +0000 (23:20 -0700)
  sets power scaler
  does test fire
Add Dynamic Menu class
Add Goto park position and set park position for CNC mode
Add current laser power value (S value) to watch screen

src/modules/tools/laser/Laser.cpp
src/modules/tools/laser/Laser.h
src/modules/utils/panel/Panel.cpp
src/modules/utils/panel/screens/DynMenuScreen.cpp [new file with mode: 0644]
src/modules/utils/panel/screens/DynMenuScreen.h [new file with mode: 0644]
src/modules/utils/panel/screens/ModifyValuesScreen.cpp
src/modules/utils/panel/screens/cnc/JogScreen.cpp
src/modules/utils/panel/screens/cnc/LaserScreen.cpp [new file with mode: 0644]
src/modules/utils/panel/screens/cnc/LaserScreen.h [new file with mode: 0644]
src/modules/utils/panel/screens/cnc/MainMenuScreen.cpp
src/modules/utils/panel/screens/cnc/WatchScreen.cpp

index de6e8cd..ee5c978 100644 (file)
 #include "Pin.h"
 #include "Gcode.h"
 #include "PwmOut.h" // mbed.h lib
+#include "PublicDataRequest.h"
 
 #include <algorithm>
 
+#define laser_checksum                          CHECKSUM("laser")
 #define laser_module_enable_checksum            CHECKSUM("laser_module_enable")
 #define laser_module_pin_checksum               CHECKSUM("laser_module_pin")
 #define laser_module_pwm_pin_checksum           CHECKSUM("laser_module_pwm_pin")
@@ -108,6 +110,7 @@ void Laser::on_module_loaded()
     this->register_for_event(ON_HALT);
     this->register_for_event(ON_GCODE_RECEIVED);
     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);
@@ -151,6 +154,17 @@ void Laser::on_console_line_received( void *argument )
     }
 }
 
+// returns instance
+void Laser::on_get_public_data(void* argument)
+{
+    PublicDataRequest* pdr = static_cast<PublicDataRequest*>(argument);
+
+    if(!pdr->starts_with(laser_checksum)) return;
+    pdr->set_data_ptr(this);
+    pdr->set_taken();
+}
+
+
 void Laser::on_gcode_received(void *argument)
 {
     Gcode *gcode = static_cast<Gcode *>(argument);
index fa7ad4b..bc1ef0d 100644 (file)
@@ -25,12 +25,16 @@ class Laser : public Module{
         void on_halt(void* argument);
         void on_gcode_received(void *argument);
         void on_console_line_received(void *argument);
+        void on_get_public_data(void* argument);
+
+        void set_scale(float s) { scale= s/100; }
+        float get_scale() const { return scale*100; }
+        bool set_laser_power(float p);
 
     private:
         uint32_t set_proportional_power(uint32_t dummy);
         bool get_laser_power(float& power) const;
         float current_speed_ratio(const Block *block) const;
-        bool set_laser_power(float p);
 
         mbed::PwmOut *pwm_pin;    // PWM output to regulate the laser power
         Pin *ttl_pin;                          // TTL output to fire laser
index e5aa47b..e0a9946 100644 (file)
@@ -64,7 +64,7 @@
 #define hotend_temp_checksum CHECKSUM("hotend_temperature")
 #define bed_temp_checksum    CHECKSUM("bed_temperature")
 #define panel_display_message_checksum CHECKSUM("display_message")
-#define laser_module_enable_checksum CHECKSUM("laser_module_enable")
+#define laser_checksum CHECKSUM("laser")
 
 Panel* Panel::instance= nullptr;
 
@@ -180,9 +180,6 @@ void Panel::on_module_loaded()
 //    this->back_button.set_longpress_delay(longpress_delay);
 //    this->pause_button.set_longpress_delay(longpress_delay);
 
-    // see if laser module is enabled
-    laser_enabled= THEKERNEL->config->value(laser_module_enable_checksum)->by_default(false)->as_bool();
-
     THEKERNEL->slow_ticker->attach( 50,  this, &Panel::button_tick );
     if(lcd->encoderReturnsDelta()) {
         // panel handles encoder pins and returns a delta
@@ -352,6 +349,11 @@ void Panel::on_idle(void *argument)
         // Default top screen
         this->top_screen= new MainMenuScreen();
         this->custom_screen->set_parent(this->top_screen);
+
+        // see if laser module is enabled
+        void *dummy;
+        this->laser_enabled= PublicData::get_value(laser_checksum, (void *)&dummy);
+
         this->start_up = false;
         return;
     }
diff --git a/src/modules/utils/panel/screens/DynMenuScreen.cpp b/src/modules/utils/panel/screens/DynMenuScreen.cpp
new file mode 100644 (file)
index 0000000..81ec923
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "DynMenuScreen.h"
+#include "libs/Kernel.h"
+#include "Config.h"
+#include "checksumm.h"
+#include "LcdBase.h"
+#include "Panel.h"
+#include "ConfigValue.h"
+
+#include <string.h>
+
+#include <algorithm>
+
+DynMenuScreen::DynMenuScreen()
+{
+    on_exit_cmd= nullptr;
+    on_exit_fnc= nullptr;
+}
+
+DynMenuScreen::~DynMenuScreen()
+{
+    // free up the strdup() name and command
+    for(auto &i : menu_items) {
+        free(std::get<0>(i));
+        if(std::get<3>(i)) free(std::get<2>(i)); // if it was a gcode
+    }
+
+    if(on_exit_cmd != nullptr) free(on_exit_cmd);
+}
+
+void DynMenuScreen::on_exit()
+{
+    if(on_exit_cmd != nullptr) {
+        send_command(on_exit_cmd);
+    }
+    if(on_exit_fnc) {
+        on_exit_fnc();
+    }
+    delete this;
+}
+
+void DynMenuScreen::on_enter()
+{
+    THEPANEL->enter_menu_mode();
+    THEPANEL->setup_menu(menu_items.size() + 1);
+    this->refresh_menu();
+}
+
+void DynMenuScreen::on_refresh()
+{
+    if ( THEPANEL->menu_change() ) {
+        this->refresh_menu();
+    }
+
+    if ( THEPANEL->click() ) {
+        this->clicked_menu_entry(THEPANEL->get_menu_current_line());
+    }
+}
+
+void DynMenuScreen::display_menu_line(uint16_t line)
+{
+    if (line == 0) {
+        THEPANEL->lcd->printf("Back");
+    } else {
+        line--;
+        const char *name = std::get<0>(menu_items[line]);
+        THEPANEL->lcd->printf("%-20s", name);
+    }
+}
+
+void DynMenuScreen::clicked_menu_entry(uint16_t line)
+{
+    if (line == 0) {
+        THEPANEL->enter_screen(this->parent);
+
+    } else {
+        if(std::get<3>(menu_items[line-1])) {
+            // it is a gcode or command so must be executed in main loop
+            send_command(std::get<2>(menu_items[line-1]));
+
+        }else{
+            // probably a new screen or function call
+            std::get<1>(menu_items[line-1])();
+        }
+    }
+}
+
+void DynMenuScreen::addMenuItem(const MenuItemType& item)
+{
+    menu_items.push_back(item);
+}
+
+void DynMenuScreen::addMenuItem(const char *name, std::function<void(void)> func)
+{
+    string n(name);
+    if(n.size() > 20) {
+        n= n.substr(0, 20);
+    }
+    addMenuItem(make_tuple(strdup(n.c_str()), func, nullptr, false));
+}
+
+void DynMenuScreen::addMenuItem(const char *name, const char *gcode)
+{
+    string n(name);
+    if(n.size() > 20) {
+        n= n.substr(0, 20);
+    }
+    addMenuItem(make_tuple(strdup(n.c_str()), nullptr, strdup(gcode), true));
+}
+
+void DynMenuScreen::on_exit_action(const char *cmd)
+{
+    on_exit_cmd= strdup(cmd);
+}
+
+void DynMenuScreen::on_exit_action(std::function<void()> fnc)
+{
+    on_exit_fnc= fnc;
+}
diff --git a/src/modules/utils/panel/screens/DynMenuScreen.h b/src/modules/utils/panel/screens/DynMenuScreen.h
new file mode 100644 (file)
index 0000000..aa0d2ac
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+#include "PanelScreen.h"
+
+#include <string>
+#include <vector>
+#include <tuple>
+#include <functional>
+
+class DynMenuScreen : public PanelScreen
+{
+public:
+    DynMenuScreen();
+    virtual ~DynMenuScreen();
+
+    void on_refresh();
+    void on_enter();
+    void on_exit();
+
+    void display_menu_line(uint16_t line);
+    void clicked_menu_entry(uint16_t line);
+    int idle_timeout_secs(){ return timeout; }
+    void set_timeout(int n) { timeout= n; }
+    void addMenuItem(const char *name, std::function<void()> fnc);
+    void addMenuItem(const char *name, const char *gcode);
+    void on_exit_action(const char *);
+    void on_exit_action(std::function<void()>);
+
+private:
+    using MenuItemType = std::tuple<char *, std::function<void()>, char *, bool>;
+    void addMenuItem(const MenuItemType& item);
+    int timeout{60};
+
+    // name, function, command, type
+    std::vector<MenuItemType> menu_items;
+    std::function<void()> on_exit_fnc;
+    char *on_exit_cmd;
+};
index 2a044cd..a65c06e 100644 (file)
@@ -60,7 +60,7 @@ void ModifyValuesScreen::on_refresh()
         if ( THEPANEL->click() ) {
             // done changing value
             this->new_value = THEPANEL->get_control_value();
-            execute_function= selected_item; // this causes on_main_loop to change the value
+            if(!this->instant) execute_function= selected_item; // this causes on_main_loop to change the value
             this->control_mode = MENU_CONTROL_MODE;
             THEPANEL->enter_menu_mode(true);
 
index bc6510f..00e9ece 100644 (file)
@@ -31,7 +31,7 @@ JogScreen::JogScreen()
 void JogScreen::on_enter()
 {
     THEPANEL->enter_menu_mode();
-    THEPANEL->setup_menu(8);
+    THEPANEL->setup_menu(10);
     this->refresh_menu();
 }
 
@@ -56,6 +56,8 @@ void JogScreen::display_menu_line(uint16_t line)
         case 5: THEPANEL->lcd->printf("Move  0.001     "); break;
         case 6: THEPANEL->lcd->printf("MPG mode        "); break;
         case 7: THEPANEL->lcd->printf("Feed Rates      "); break;
+        case 8: THEPANEL->lcd->printf("Goto Park Posn  "); break;
+        case 9: THEPANEL->lcd->printf("Set Park Posn   "); break;
     }
 }
 
@@ -78,6 +80,9 @@ void JogScreen::clicked_menu_entry(uint16_t line)
         case 7:
             set_feed_rates();
             dojog= false;
+        case 8: send_command("G28"); dojog= false; break;
+        case 9: send_command("G28.1"); dojog= false; break;
+
     }
 
     if(dojog) {
diff --git a/src/modules/utils/panel/screens/cnc/LaserScreen.cpp b/src/modules/utils/panel/screens/cnc/LaserScreen.cpp
new file mode 100644 (file)
index 0000000..b365452
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "LaserScreen.h"
+
+#include "Kernel.h"
+#include "Panel.h"
+#include "PanelScreen.h"
+#include "LcdBase.h"
+#include "ModifyValuesScreen.h"
+#include "DynMenuScreen.h"
+#include "PublicData.h"
+#include "checksumm.h"
+
+#ifndef NO_TOOLS_LASER
+#include "Laser.h"
+#endif
+
+#include <string>
+
+using namespace std;
+
+#define laser_checksum CHECKSUM("laser")
+
+LaserScreen::LaserScreen()
+{
+}
+
+void LaserScreen::on_enter()
+{
+    THEPANEL->enter_menu_mode();
+    THEPANEL->setup_menu(3);
+    this->refresh_menu();
+}
+
+void LaserScreen::on_exit()
+{
+    delete this; // self deleting
+}
+
+void LaserScreen::on_refresh()
+{
+    if ( THEPANEL->menu_change() ) {
+        this->refresh_menu();
+    }
+    if ( THEPANEL->click() ) {
+        this->clicked_menu_entry(THEPANEL->get_menu_current_line());
+    }
+}
+
+void LaserScreen::display_menu_line(uint16_t line)
+{
+    switch ( line ) {
+        case 0: THEPANEL->lcd->printf("Back");  break;
+        case 1: THEPANEL->lcd->printf("Set Power Scale"); break;
+        case 2: THEPANEL->lcd->printf("Test Fire");  break;
+    }
+}
+
+void LaserScreen::clicked_menu_entry(uint16_t line)
+{
+    switch ( line ) {
+        case 0: THEPANEL->enter_screen(this->parent); return;
+        case 1: setPowerScreen(); break;
+        case 2: testFireScreen(); break;
+    }
+}
+
+void LaserScreen::testFireScreen()
+{
+    auto dms= new DynMenuScreen();  // self delete on exit
+    dms->set_parent(this->parent); // because this will have been deleted when it exits
+    dms->set_timeout(10); // 10 seconds and it will turn off
+    dms->on_exit_action("fire off");
+    dms->addMenuItem("Off", "fire off");
+    dms->addMenuItem("Low", "fire 10");
+    dms->addMenuItem("1/4", "fire 25");
+    dms->addMenuItem("Half", "fire 50");
+    dms->addMenuItem("3/4",  "fire 75");
+    dms->addMenuItem("Full", "fire 100");
+    THEPANEL->enter_screen(dms);
+}
+
+void LaserScreen::setPowerScreen()
+{
+    auto mvs= new ModifyValuesScreen(true);  // self delete on exit
+    mvs->set_parent(this->parent); // because this will have been deleted when it exits
+
+    #ifndef NO_TOOLS_LASER
+    Laser *plaser;
+    if(PublicData::get_value(laser_checksum, (void *)&plaser) || plaser == nullptr) {
+
+        mvs->addMenuItem("Power %",
+            [plaser]() -> float { return plaser->get_scale(); },
+            [plaser](float v) { plaser->set_scale(v); },
+            1.0F,
+            0.0F,
+            200.0F,
+            true // instant
+            );
+    }
+    #endif
+
+    THEPANEL->enter_screen(mvs);
+}
diff --git a/src/modules/utils/panel/screens/cnc/LaserScreen.h b/src/modules/utils/panel/screens/cnc/LaserScreen.h
new file mode 100644 (file)
index 0000000..9b99c1b
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include "PanelScreen.h"
+
+class LaserScreen : public PanelScreen
+{
+public:
+    LaserScreen();
+    void on_refresh();
+    void on_enter();
+    void on_exit();
+    void display_menu_line(uint16_t line);
+    void clicked_menu_entry(uint16_t line);
+    int idle_timeout_secs() { return 60; }
+
+private:
+    void testFireScreen();
+    void setPowerScreen();
+};
index 272cedd..3fd304f 100644 (file)
@@ -119,7 +119,7 @@ void MainMenuScreen::display_menu_line(uint16_t line)
         case 4: THEPANEL->lcd->printf("Custom"); break;
         case 5: THEPANEL->lcd->printf("Configure"); break;
         case 6: THEPANEL->lcd->printf("Probe"); break;
-        case 7: if(THEPANEL->has_laser()) THEPANEL->lcd->printf("Laser"); break;
+        case 7: THEPANEL->lcd->printf("Laser"); break; // only used if THEPANEL->has_laser()
     }
 }
 
@@ -138,7 +138,7 @@ void MainMenuScreen::clicked_menu_entry(uint16_t line)
         case 4: THEPANEL->enter_screen(THEPANEL->custom_screen ); break;
         case 5: setupConfigureScreen(); break;
         case 6: THEPANEL->enter_screen((new ProbeScreen())->set_parent(this)); break;
-        case 7: if(THEPANEL->has_laser()) THEPANEL->enter_screen((new LaserScreen())->set_parent(this)); break; // self deleting
+        case 7: THEPANEL->enter_screen((new LaserScreen())->set_parent(this)); break; // self deleting, only used if THEPANEL->has_laser()
     }
 }
 
index 32cb96b..fc38cef 100644 (file)
@@ -48,7 +48,7 @@ WatchScreen::~WatchScreen()
 void WatchScreen::on_enter()
 {
     THEPANEL->lcd->clear();
-    THEPANEL->setup_menu(7);
+    THEPANEL->setup_menu(8);
     get_current_status();
     get_wpos();
     get_sd_play_info();
@@ -187,7 +187,8 @@ void WatchScreen::display_menu_line(uint16_t line)
             THEROBOT->from_millimeters(THEKERNEL->conveyor->get_current_feedrate()*60.0F));
             break;
         case 5: THEPANEL->lcd->printf("%3d%% %2lu:%02lu %3u%% sd", this->current_speed, this->elapsed_time / 60, this->elapsed_time % 60, this->sd_pcnt_played); break;
-        case 6: THEPANEL->lcd->printf("%19s", this->get_status()); break;
+        case 6: if(THEPANEL->has_laser()) THEPANEL->lcd->printf("Laser power %1.4f", THEROBOT->get_s_value()); break;
+        case 7: THEPANEL->lcd->printf("%19s", this->get_status()); break;
     }
 }