/ adafruit_thermal_printer / thermal_printer_legacy.py
thermal_printer_legacy.py
  1  # The MIT License (MIT)
  2  #
  3  # Copyright (c) 2017 Tony DiCola
  4  #
  5  # Permission is hereby granted, free of charge, to any person obtaining a copy
  6  # of this software and associated documentation files (the "Software"), to deal
  7  # in the Software without restriction, including without limitation the rights
  8  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9  # copies of the Software, and to permit persons to whom the Software is
 10  # furnished to do so, subject to the following conditions:
 11  #
 12  # The above copyright notice and this permission notice shall be included in
 13  # all copies or substantial portions of the Software.
 14  #
 15  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 20  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 21  # THE SOFTWARE.
 22  """
 23  `adafruit_thermal_printer.thermal_printer_legacy.ThermalPrinter`
 24  =================================================================
 25  
 26  Thermal printer control module built to work with small serial thermal
 27  receipt printers.  Note that these printers have many different firmware
 28  versions and care must be taken to select the appropriate module inside this
 29  package for your firmware printer:
 30  
 31  * thermal_printer = The latest printers with firmware version 2.68+
 32  * thermal_printer_264 = Printers with firmware version 2.64 up to 2.68.
 33  * thermal_printer_legacy = Printers with firmware version before 2.64.
 34  
 35  * Author(s): Tony DiCola
 36  """
 37  from micropython import const
 38  
 39  import adafruit_thermal_printer.thermal_printer as thermal_printer
 40  
 41  
 42  __version__ = "0.0.0-auto.0"
 43  __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Thermal_Printer.git"
 44  
 45  
 46  # pylint: disable=bad-whitespace
 47  # Internally used constants.
 48  _INVERSE_MASK = const(1 << 1)  # Not in 2.6.8 firmware
 49  # pylint: enable=bad-whitespace
 50  
 51  
 52  # Legacy behavior class for printers with firmware before 2.64.
 53  # See the comments in thermal_printer.py to understand how this class overrides
 54  # methods which change for older firmware printers!
 55  class ThermalPrinter(thermal_printer.ThermalPrinter):
 56      """Thermal printer for printers with firmware version before 2.64."""
 57  
 58      # pylint: disable=bad-whitespace
 59      # Barcode types.  These vary based on the firmware version so are made
 60      # as class-level variables that users can reference (i.e.
 61      # ThermalPrinter.UPC_A, etc) and write code that is independent of the
 62      # printer firmware version.
 63      UPC_A = 0
 64      UPC_E = 1
 65      EAN13 = 2
 66      EAN8 = 3
 67      CODE39 = 4
 68      I25 = 5
 69      CODEBAR = 6
 70      CODE93 = 7
 71      CODE128 = 8
 72      CODE11 = 9
 73      MSI = 10
 74      # pylint: enable=bad-whitespace
 75  
 76      def __init__(
 77          self, uart, byte_delay_s=0.00057346, dot_feed_s=0.0021, dot_print_s=0.03
 78      ):
 79          """Thermal printer class.  Requires a serial UART connection with at
 80          least the TX pin connected.  Take care connecting RX as the printer
 81          will output a 5V signal which can damage boards!  If RX is unconnected
 82          the only loss in functionality is the has_paper function, all other
 83          printer functions will continue to work.  The byte_delay_s, dot_feed_s,
 84          and dot_print_s values are delays which are used to prevent overloading
 85          the printer with data.  Use the default delays unless you fully
 86          understand the workings of the printer and how delays, baud rate,
 87          number of dots, heat time, etc. relate to each other.
 88          """
 89          super().__init__(
 90              uart,
 91              byte_delay_s=byte_delay_s,
 92              dot_feed_s=dot_feed_s,
 93              dot_print_s=dot_print_s,
 94          )
 95  
 96      def print_barcode(self, text, barcode_type):
 97          """Print a barcode with the specified text/number (the meaning
 98          varies based on the type of barcode) and type.  Type is a value from
 99          the datasheet or class-level variables like UPC_A, etc. for
100          convenience.  Note the type value changes depending on the firmware
101          version so use class-level values where possible!
102          """
103          assert 0 <= barcode_type <= 255
104          assert 0 <= len(text) <= 255
105          self.feed(1)  # Recent firmware can't print barcode w/o feed first???
106          self.send_command("\x1DH\x02")  # Print label below barcode
107          self.send_command("\x1Dw\x03")  # Barcode width 3 (0.375/1.0mm thin/thick)
108          self.send_command("\x1Dk{0}".format(chr(barcode_type)))  # Barcode type
109          # Pre-2.64 firmware prints the text and then a null character to end.
110          # Instead of the length of text as a prefix.
111          self.send_command(text)
112          self.send_command("\x00")
113          self._set_timeout((self._barcode_height + 40) * self._dot_print_s)
114          self._column = 0
115  
116      def reset(self):
117          """Reset the printer."""
118          # Issue a reset command to the printer. (ESC + @)
119          self.send_command("\x1B@")
120          # Reset internal state:
121          self._column = 0
122          self._max_column = 32
123          self._char_height = 24
124          self._line_spacing = 6
125          self._barcode_height = 50
126          # Skip tab configuration on older printers.
127  
128      def feed(self, lines):
129          """Advance paper by specified number of blank lines."""
130          # Just send line feeds for older printers.
131          for _ in range(lines):
132              self._write_char("\n")
133  
134      def has_paper(self):
135          """Return a boolean indicating if the printer has paper.  You MUST have
136          the serial RX line hooked up for this to work.
137  
138          .. note::
139  
140              be VERY CAREFUL to ensure your board can handle a 5V serial
141              input before hooking up the RX line!
142  
143          """
144          # The paper check command is different for older firmware:
145          self.send_command("\x1Br\x00")  # ESC + 'r' + 0
146          status = self._uart.read(1)
147          if status is None:
148              return False
149          return not status[0] & 0b00000100
150  
151      # Inverse on older printers (pre 2.68) uses a print mode bit instead of
152      # specific commands.
153      inverse = thermal_printer.ThermalPrinter._PrintModeBit(_INVERSE_MASK)