Printing devices

Files CCore/inc/Print.h CCore/src/Print.cpp

Subfolders CCore/inc/print CCore/src/print

There are several standard "printing device" classes, implemented in CCore. Lists are differ in XCore and HCore.

PrintCon (HCore)

PrintCon is the first and the most important class in the list. It is used to print to the console. This class is based on the target function ConWrite, declared in the header sys/SysCon.h. This function is assumed to call some native OS function to print the text string.


void Sys::ConWrite(StrLen str) noexcept;

The word Con is used to print to the console.


/* words */ 

enum ConType { Con };
 
template <> 
struct PrintOutAdapter<ConType>
 {
  using PrintOutType = PrintCon ;
 };

template <> 
struct PrintOutAdapter<const ConType>
 {
  using PrintOutType = PrintCon ;
 };

The class PrintCon uses a small stack buffer to accumulate the incoming text stream:


class PrintCon : public PrintBase
 {
   char buf[TextBufLen];
 
  private:
  
   virtual PtrLen<char> do_provide(ulen hint_len);
   
   virtual void do_flush(char *ptr,ulen len); 
   
  public:
  
   PrintCon() {}

   explicit PrintCon(ConType) {}
   
   ~PrintCon() { flush(); }
   
   static void Print(const char *ptr,ulen len) { Print(Range(ptr,len)); }
   
   static void Print(StrLen str); // ignore errors
 };

The static methods Print() can be used for the direct printing to the console.

PrintCon (XCore)

The XCore variant of the PrintCon is close to the HCore.


class PrintCon : public PrintBase
 {
   MSec timeout;
   NanoPacket<char> packet;
 
  private:
  
   virtual PtrLen<char> do_provide(ulen hint_len);
   
   virtual void do_flush(char *ptr,ulen len); 
   
  public:

   explicit PrintCon(MSec timeout_=DefaultTimeout) : timeout(timeout_) {}
  
   explicit PrintCon(ConType,MSec timeout_=DefaultTimeout) : timeout(timeout_) {}
   
   ~PrintCon() { flush(); }
   
   static void Print(const char *ptr,ulen len); // ignore errors
   
   static void Print(StrLen str) { Print(str.ptr,str.len); } 
 };

The small difference is the constructor takes the additional argument timeout, defaulted to the DefaultTimeout. The main difference, however, is not the interface, but the implementation. XCore PrintCon uses NanoPackets. Methods Print() create a temporary PrintCon object to print the text. Printing is not permitted in the interrupt context.

XCore supports the console printing by the following functions, declared in the sys/SysCon.h header.


NanoPacket<char> Sys::AllocConPacket(MSec timeout);

void Sys::ConWrite(NanoPacket<char> packet);

The full implementation of these functions is the target resposibility. For this a derived class from the Sys::ConBase class is defined. Usually a target device has a serial port and console packets are delivered to the host computer through the port driver.

PrintFile (HCore only)

PrintFile class is designed to print to a file. On HCore targets this class is based on OS native file input-output functions.


class PrintFile : public PrintBase
 {
   ....
   
  public:
   
   // constructors
  
   PrintFile() noexcept;
   
   explicit PrintFile(StrLen file_name,FileOpenFlags oflags=Open_ToWrite);
   
   ~PrintFile();
   
   // methods
   
   bool isOpened() const;
   
   void open(StrLen file_name,FileOpenFlags oflags=Open_ToWrite);
   
   void disableExceptions(); 
   
   void soft_close(FileMultiError &errout);
   
   void close();
   
   void preserveFile();
 };

PrintFile object can be opened or closed. To print to the particular file, the PrintFile object must be opened and the file name and open flags must be provided. It can be done using the constructor or the method open(). Default constructor creates an object in the closed state. Non-default opens a file. In case of error an exception is thrown.

Destructor flushes and closes opened object. Errors are reported.

isOpened() returns true, if the file is opened, and false otherwise.

open() opens a closed object with the given file and open flags. In case of error an exception is thrown.

close() closes an opened object. In case of error and if there is a pending output error an exception is thrown.

soft_close() does not throw, it returns a group of errors using the FileMultiError object.

disableExceptions() disables exceptions during print operations. You may call this method after the open(). If exceptions are disabled, the special internal error flag is set in case of printing error. This flag is added in the error list during a close operation.

preserveFile() preserves a file, opened with the AutoDelete open flag.

PrintFile class is constructed from two classes: SafeBuf and RawFileToPrint.

The SafeBuf class is used to allocate a file buffer. PrintFile uses the file buffer of size 64 KBytes. But if the required memory is not available, SafeBuf uses an internal small safeguard buffer of size 32 bytes.


class RawFileToPrint : NoCopy
 {
   Sys::File file;
   bool opened;
   bool preserve_file;
   
  public:
   
   // constructors
  
   RawFileToPrint() : opened(false) {}
   
    // No destructor ! 
   
   // methods
   
   bool isOpened() const { return opened; }
   
   FileError open(StrLen file_name,FileOpenFlags oflags);
   
   void close(FileMultiError &errout);
   
   void preserveFile() { preserve_file=true; }
   
   FileError write(const uint8 *buf,ulen len);
 }; 

The RawFileToPrint class is built on the target class Sys::File, declared in the header sys/SysFile.h. It performs open/close operations and the raw file output.

The target Sys::File class implements the classical set of file operations.


struct Sys::File
 {
  // private

  ....

  // public
  
  struct IOResult
   {
    ulen len;
    FileError error;
   };
 
  struct PosResult
   {
    FilePosType pos;
    FileError error;
   };
  
  FileError open(StrLen file_name,FileOpenFlags oflags) noexcept;
 
  void close(FileMultiError &errout,bool preserve_file=false) noexcept; 
  
  void close() noexcept; 
   
  IOResult write(const uint8 *buf,ulen len) noexcept;
  
  IOResult read(uint8 *buf,ulen len) noexcept;
  
  PosResult getLen() noexcept;
  
  PosResult getPos() noexcept;
  
  FileError setPos(FilePosType pos) noexcept;
 };

Methods of this class call directly OS file system interface functions.

PrintAsyncFile

PrintAsyncFile is built using the AsyncFile class. Output stream is buffered using packet data buffers. Once a packet is filled, it is submitted to the AsyncFile object, the packet may be sent to the target device asynchronously.


class PrintAsyncFile : public PrintBase
 {
   AsyncFile file;

   ....

  public:
   
   // constructors
  
   explicit PrintAsyncFile(MSec timeout=DefaultTimeout,ulen max_packets=DefaultMaxPackets);
   
   explicit PrintAsyncFile(StrLen file_name,FileOpenFlags oflags=Open_ToWrite,MSec timeout=DefaultTimeout,ulen max_packets=DefaultMaxPackets);
   
   PrintAsyncFile(StrLen dev_name,StrLen dev_file_name,FileOpenFlags oflags=Open_ToWrite,MSec timeout=DefaultTimeout,ulen max_packets=DefaultMaxPackets);

   ~PrintAsyncFile();
   
   // methods
   
   bool isOpened() const { return file.isOpened(); }
   
   void setFinalTimeout(MSec t) { file.setFinalTimeout(t); }

   void open(StrLen file_name,FileOpenFlags oflags=Open_ToWrite);
   
   void open(StrLen dev_name,StrLen dev_file_name,FileOpenFlags oflags=Open_ToWrite);

   void exec2(StrLen dir,StrLen program,MSec timeout=DefaultTimeout,ulen max_packets=DefaultMaxPackets);
   
   void exec2(AsyncFileSystem &fs,StrLen dev_dir,StrLen dev_program);
   
   void soft_close(FileMultiError &errout);
   
   void close();
   
   void preserveFile() { file.preserveFile(); }
   
   void setLargeWriteLen(ulen large_write_len) { file.setLargeWriteLen(large_write_len); }
   
   void wait() { file.wait(); }
   
   void wait_final() { file.wait_final(); }
   
   void wait(MSec timeout) { file.wait(timeout); }
   
   void cancel_and_wait() { file.cancel_and_wait(); }
 };

A file must be opened before a printing. You can do it using the constructor or the method open(). Constructors arguments timeout and max_packets are propagated to the inner AsyncFile object. file_name and open_flags specifies the file to be opened and the open flags. The file may be also specified using the device name and the device file name.

Destructor completes operations, closes the file and reports errors if any.

isOpened() returns true, if the file is opened.

setFinalTimeout() sets the "final timeout".

open() opens the given file.

exec2() methods are used to execute a program. Some AsyncFileSystem object is involved. Once you "open" a file with this method, you may print the program command-line. To run a program, you have to call the method preserveFile() and close the file. The first variant creates a temporary AsyncFileSystem object with the device name found in arguments (both device names in dir and program must be the same). Additional arguments are applied to this object.

soft_close() flushes output and closes the file. Errors are reported to the given FileMultiError object.

close() flushes output and closes the file. An exception is thrown in case of errors.

preserveFile() preserves the file, opened with the Open_AutoDelete open flag.

Other methods are direct calls of the correspondent AsyncFile methods. Usually they are not required.

PrintPTPCon

This class uses the PTP Console protocol to print over a net.


class PrintPTPCon : public PrintBase
 {
   ....

  public:
  
   explicit PrintPTPCon(StrLen con_dev_name,MSec timeout=DefaultTimeout,ulen max_packets=DefaultMaxPackets); 
   
   ~PrintPTPCon();
   
   void enableExceptions() { enable_exceptions=true; }
   
   void flush_and_wait();
 };

Constructor connects to the PTP Con client device.

enableExceptions() enables exception generation during printing.

flush_and_wait() flushes stream and waits until PTP operations are finished (up to timeout).

Before printing to the PTP Con device, console must be opened. You can do it using the class PTPConOpenClose.


class PTPConOpenClose : NoCopy
 {
   ....

  public: 
   
   // constructors
  
   PTPConOpenClose(StrLen con_dev_name,StrLen name,const Net::PTPCon::Cfg &cfg=DefaultValue());
   
   ~PTPConOpenClose();
   
   // read
   
   using InputProc = Net::PTPCon::ClientDevice::InputProc ;
  
   void start_read(InputProc *proc) { con->start_read(proc); }
   
   void stop_read() { con->stop_read(); }
   
   // write
   
   PacketFormat getWriteFormat() const { return format; }
   
   void write(Packet<uint8> packet) { con->write(packet); }
 };

Constructor opens a console with the given name and configuration properties. Destructor closes it.

This class also can be used to read or write PTP Con device, using "raw" methods. But it is better to use classes, intended for printing or console reading.