1 /* 2 This file is a part of the RepSnapper project. 3 Copyright (C) 2011-12 martin.dieringer@gmx.de 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Lesser General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public License along 16 with this program; if not, write to the Free Software Foundation, Inc., 17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 #pragma once 21 22 #include <limits.h> 23 24 #include "thread.h" 25 #include "thread_buffer.h" 26 #include "printer_serial.h" 27 28 using namespace std; 29 30 class ThreadedPrinterSerial : protected PrinterSerial 31 { 32 static const unsigned long command_buffer_size = 8192; 33 static const unsigned long response_buffer_size = 4096; 34 static const unsigned long log_buffer_size = 8192; 35 36 static const ntime_t command_buffer_sleep; 37 static const ntime_t response_buffer_sleep; 38 static const ntime_t log_buffer_sleep; 39 static const ntime_t helper_thread_sleep; 40 41 // Rules: 42 // request_print, is_printing, and printer_commands are initialized to NULL 43 // To stop printing, thread must lock the mutex, set request_print to false 44 // and wait for the helper to signal on pc_cond. Finally, release the 45 // mutex. 46 // To start printing, lock the mutex, if is_printing is true, stop printing 47 // per the above steps. Next, set printer commands to the desired commands 48 // and clear ps_status. Then, set request_print to true and wait for 49 // the helper to signal on pc_cond. Finally, release the mutex. 50 // For the purpose of status bars and status lights, 51 // the values of is_printing and pc_status can be examined without needing 52 // to lock the mutex. 53 // 54 // Helper: 55 // if request_print is different than is_printing, aquire the mutex, 56 // set is_printing to match request_print, signal on pc_cond, and relase 57 // the mutex. 58 // <<handle queued commands> 59 // if is_printing, send the next command from printer_commands. Do NOT 60 // need to lock the mutex. 61 62 mutex_t pc_mutex; 63 bool request_print; // set by main thread(s), pc_mutex required 64 bool is_printing; // set by helper, pc_cond_mutex required 65 bool printing_complete; // set by helper, no mutex required 66 cond_t pc_cond; // signaled by helper, pc_mutex and pc_cond_mutex required 67 mutex_t pc_cond_mutex; 68 const char *printer_commands; // set by main thread(s), pc_mutex required 69 unsigned long pc_lines_printed; // when is_printing is false, set by main thread(s), pc_mutex required. When is_printing is true, set by helper, pc_mutex requried 70 unsigned long pc_bytes_printed; // when is_printing is false, set by main thread(s), pc_mutex required. When is_printing is true, set by helper, pc_mutex required 71 unsigned long pc_stop_line; // set by main thread(s), pc_mutex required 72 int inhibit_count; // set by main thread(s), pc_cond_mutex required 73 74 ThreadBufferReturnData command_buffer; 75 SignalingThreadBuffer response_buffer; 76 ThreadBuffer log_buffer; 77 ThreadBuffer error_buffer; 78 79 bool helper_active; 80 thread_t helper_thread; 81 bool helper_cancel; 82 83 ThreadBufferReturnData::ReturnData *return_data; 84 85 void CheckPrintingState( void ); // Check if main thread is requesting printing and set helper thread switches accordingly 86 87 void SendNextPrinterCommand( void ); 88 void SendCommand( bool buffer_response ); 89 90 void RecvTimeout( void ); 91 void LogLine( const char *line ); // Log the line. The provided line should end in a newline character. 92 void LogError( const char *error_line ); // Log the error. The provided line should end in a newline character. 93 94 static void *HelperMainStatic( void *arg ); 95 void *HelperMain( void ); 96 97 public: 98 ThreadedPrinterSerial(); 99 virtual ~ThreadedPrinterSerial(); 100 101 // Connect to or disconnect from a printer 102 virtual bool Connect( string device, int baudrate ); 103 virtual void Disconnect( void ); 104 virtual bool IsConnected( void ); 105 virtual bool Reset( void ); 106 107 // Start printing gcode 108 // Commands are sent one at a time in the background 109 // Send and SendAndWaitResponse can safely be sent 110 // while printing. 111 virtual bool StartPrinting( string commands, unsigned long start_line = 1, unsigned long stop_line = ULONG_MAX ); 112 virtual bool IsPrinting( void ); 113 virtual bool StopPrinting( bool wait = true ); 114 virtual bool ContinuePrinting( bool wait = true ); 115 virtual void Inhibit( bool value = true ); 116 virtual bool IsInhibited( void ); 117 118 unsigned long GetPrintingProgress( unsigned long *bytes_printed = NULL ); 119 // Returns last line number ok'd by the printer 120 // If printing is stopped, returns last line number of previous print 121 // If bytes_printed is non-null, sets that value as well. 122 123 unsigned long GetTotalPrintingLines( void ); 124 // Return the ending line of the current print 125 126 using PrinterSerial::Send; 127 bool SendAsync( char const * command ); 128 bool Send( string command ); 129 // Command may be multiple commands separated by newlines (\n). 130 // Such commands are queued atomically. 131 // Commands may be sent when printing is active. 132 // Commands sent with this interface have higher priority than commands 133 // sent from StartPrinting. 134 135 string ReadResponse( bool wait = false ); 136 // returns "" if wait is false and no response is ready 137 // only returns responses from Send() and StartPeriodic() and NOT from 138 // SendAndWaitResponse() or StartingPrinting() 139 140 string SendAndWaitResponse( string command ); 141 // Send the string and wait for the response 142 // May take up to several seconds if the printer is already processing 143 // a long command 144 145 string ReadLog( bool wait = false ); 146 // returns "" if wait is false and no log entries are ready 147 148 string ReadErrorLog( bool wait = false ); 149 // returns "" if wait is false and no log entries are ready 150 }; 151