Forum: PC-Programmierung ESC-Sequenzen von Rechenr an Drucker decodieren


von Wolfgang (Gast)


Lesenswert?

Servus,

ich schreibe eben ein kleines Tool das die COM-Schnittstelle eines 
Microcontrollergestützten Messgeräts abfängt. Daran war früher einmal 
ein serieller 9-Nadel-Drucker von dem ich aber leider weder den Typ noch 
das exakte Protokoll kenne. Bin nun mit den Grafik und 
Formatierungsroutinen sowet fertig das diese an einem angeschlossenen 
Rechener Grafik und Text wie auf dem Papier des Druckers seitenweise in 
eine Datei geschrieben wird. Nun habe ich aber einige Probleme mit mir 
nicht mehr erklärlichen ESC-Sequenzen die ich nirgends herausfinden 
kann. Diese wären:

ESC '&' 26 6c 32 36 41
ESC '&' 61 31 32 4c
...

Normal müßte das ein Benutzerdefinierter Font sein im Aufbau:

ESC '&' NUL .......

Gleich wie ich es versuche im Hex-Editor zu zerlegen komme ich auf keine 
logischen Schlüsse. Genauso wenig wie mit der folgenden Sequenz:

ESC '*' 'b' '0' 'm' '8' '0' 'W' ....

diese wiederholt sich im seriellen Signal auch alle ca. 85 Bytes udn 
gibt keinen Sinn. nach der typischen ESC-Sequenz müßte es eine Grafik 
sein, die andere davor habe ich hinbekommen, die andere ist nicht 
lösbar.

Anbei noch meien Tests als ZIP-File udn darin auch die noname2.log die 
das binäre Protokoll von Rechner zu Drucker darstellt.

Wenn jemand was weiß wär mir schon viel geholfen, auch mit Tips für 
ESC-Listen von uralten Druckern wie LQ30 etc. Im Internet ist da leider 
kaum noch etwas zu finden ausser dei allgemeinen Standards die hier 
nicht mehr ganz zutreffen.

Mein bisheriges Tool, in der Exe den rechten "Laden" Button klicken, 
dann wird es decodiert als wärs ein Drucker
http://www.wiesolator.gotdns.org/temp/Progi.zip

Hier noch die Stelle, ab der ich nicht mehr weiterkomme:
http://www.wiesolator.gotdns.org/temp/Hex-EditorProto.gif

Grüße Wolfgang

von Rolf L. (Gast)


Lesenswert?

Hallo Wolfgang,

mein Wissen reicht noch soweit zurück, dass diese ESC-Sequenzen von
Epson abstammen und oft auf die 'Grafikfähigkeiten' einiger Drucker- 
Modelle abgestimmt waren, die grafikfähig waren.
Wenn Du noch rausbekommen könntest, welcher Drucker da ursprünglich
mal drann war, könnte man konkreter weitersuchen.
Meinens Wissens nach waren lange Zeit zwei ESC-Standards gültig:

ESC-Standard bei LX-Druckern und ESC/2 bei späteren Modellen LQ-
Modellen.

Ich hoffe, das konnte Dir weiterhelfen.

Ach ja, eingrenzen könnte mann es auch über das Alter Deines
Messsystems. Ich vermute mal ESC-Standard.

Gruss Rolf.

von Rahul, der Trollige (Gast)


Lesenswert?


von *.* (Gast)


Lesenswert?

> http://support.epson.ru/products/manuals/000350/part1.pdf

Da sind eben diese Kommandos nicht drin.

von Wolfgang S. (bluenature)


Lesenswert?

Danke für die Infos, ich bin auch so weitergekommen nach vielen Stunden 
tüften in den Hex-Bytes. Es ist ein nicht üblicher mischmasch aus 
vertikalen Grafkdaten und horizontalen Grafikdaten. Diese Kommandos 
kenne ich jedenfals von nirgends bisher obohl ich früher auch schon 
unter DOS viel programmiert habe und auch mit ESC-Kommados mit etlichen 
Druckern.
Das PDF-Dokument sowie von Star die PDF habe ich schon länger hier und 
sind so meine Nachschlagewerke. Da ist wie erwähnt nichts von diesen 
Sequenzen erwähnt.
Auf jeden Fall funktioniert der Druck nun in mehrere seitenweise 
BMP-Dateien recht gut bis auf ein paar Kommandos die ich wiederum nicht 
zuordnen konnte, die ignoriere ich nach währnd des Decodierens einfach 
da ich ihre Funktion nicht kenne. Beginne wie Grafik-Kommandos mit ESC 
'*', aber geben dann keinen logischen Sinn mehr und sind zudem zwischen 
4 udn 7 Bytes lang, danach eben das nächste ESC-Kommando.

Grüße Wolfgang

von Wolfgang S. (bluenature)


Lesenswert?

Ich habe nun die Liste aller unbekannter ESC-Sequenzen mal sauber 
katalogisiert. vieleicht weß der ein oder andere noch etwas über diese 
etwas unbekannten Kommandos etwas zu sagen in ihrer genauen Funktion.

-----------------------------------------------------------------------
ESC *r01A
ESC *rbc0U
ESC *r640S (vermutlich 640 Pixel horizontale Grafik einstellen zu 
*b0m80W)
ESC *r0q1A
ESC *rbC
ESC *t100R
ESC *p2N
ESC *b0m80W
ESC &a+180v720H
ESC &l26A
ESC &a12L
ESC &k6W
ESC (s0B
ESC (s12H
ESC (s6H
ESC (0U
ESC (s6T
-----------------------------------------------------------------------

Wie gesagt, ich kenne den Zieldrucker nicht in Typ und Fabrikat. Es gibt 
ihn nicht mehr und ich emuliere ihn per eigener Soft auf einem Laptop im 
Moment am seriellen Anschluss.

Grüße Wolfgang

von Christoph Kessler (db1uq) (Gast)


Lesenswert?

Der Begriff ESC/P ist noch nicht gefallen, ich dachte, das war die 
allgemeine Bezeichnung dafür
http://de.wikipedia.org/wiki/ESC/P

aber dort wird auch nur auf die Epson.ru-Seite verlinkt, und auf:
http://de.wikipedia.org/wiki/Escape-Sequenz - dort weiter auf HP:
http://h20000.www2.hp.com/bc/docs/support/SupportManual/bpl13210/bpl13210.pdf
dort hieß es nicht ESC/P sondern PCL

"PCL printer commands consist of two or more characters. The first
character is always the ASCII escape character"

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

"ESC/P" ist ein Epson-Druckerdialekt, der primär für Nadeldrucker 
entwickelt wurde, "PCL" ist ein sich davon vollkommen unterscheidender 
Druckerdialekt von Laser- und Tintenstrahldruckern von HP.

Andere Nadeldruckerhersteller verwende(t)en ihre eigenen Dialekte oder 
waren zu mehreren davon kompatibel. Der "IBM Proprinter" war auch ein 
verbreiteter Standard.

von Christoph Kessler (db1uq) (Gast)


Lesenswert?

Ja stimmt der Proprinter oder "Epson-Kompatibel". Ich habe mal für 
meinen Star NL-10 9-Nadler eine Grafikausgabe in Atari-Omikron-Basic 
programmiert, das waren auch ESC/P-artige ESC-Kommandos.

von Christoph Kessler (db1uq) (Gast)


Lesenswert?

und da gabs noch unseren Entwicklungschef, der höchstpersönlich den 
ersten Laserdrucker der Firma mit dem Staubsauger reinigte. Dabei fand 
er ein Haar im Drucker - den Coronadraht. Anschließend gabs von ihm 
einen Cheferlass, dass nur noch Fachleute den Drucker öffnen dürfen.
Dieser Laserdrucker ließ sich nur mit Einsteck-Cartridges auf die 
verschiedenen Druckerkompatibilitäten umstellen. Ich meine er war von 
OKI.

von Wolfgang S. (bluenature)


Lesenswert?

kein Problem, ich bin selbst auf den Trichter gekommen, waren eh nicht 
relevante Komandos. Meine Simulation ist jedenfalls lauffähig und geht 
soweit.

Attribute VB_Name = "ModEncode"

' PCL-Code encodieren in HTML-Dokument

' StretchBlt() Modes
Public Const BLACKONWHITE& = 1 ' nur für Schwarz/Weiß
Public Const WHITEONBLACK& = 2 ' nur für Schwarz/Weiß
Public Const COLORONCOLOR& = 3 ' Qualität von PaintPicture
Public Const HALFTONE& = 4     ' höchste Qualität (Mittelwert der 
Farben)
Public Const MAXSTRETCHBLTMODE& = 4

Public Declare Function SetStretchBltMode Lib "gdi32" (ByVal hdc As 
Long, _
  ByVal nStretchMode As Long) As Long

Public Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long, _
  ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight 
As Long, _
  ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, _
  ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As 
Long) As Long

Dim Modus        As String

Public CmoWork   As Boolean

Public RxBuffer  As String
Public IdleCount As Long

Dim Inhalt       As String
Dim AktPos       As Long
Dim AktChar      As String * 1
Dim SeiteNr      As Integer

Dim CurX         As Long
Dim CurY         As Long

Public Sub LoadData(ByVal FileName As String)
  ' Datei laden
  Open FileName For Binary As #1
  Inhalt = String(FileLen(FileName), " ")
  Get #1, , Inhalt
  Close #1
  ' Datei decodieren
  FrmMain.PicBlatt(1).Font.Name = "Courier New"
  FrmMain.PicBlatt(1).Font.Size = 10
  FrmMain.PicBlatt(1).Font.Bold = False
  CurX = 0
  CurY = 0
  PixelX = 640
  PixelY = 1
  SeiteNr = 0
  FrmMain.LblInfo.Caption = "Seite: " & SeiteNr + 1
  For AktPos = 1 To Len(Inhalt)
    'FrmMain.TxtAnzeige.Text = Mid(Inhalt, AktPos)
    AktChar = Mid$(Inhalt, AktPos, 1)
    ' Seitenumbruch erzwingen bei Blattende
    If CurY >= FrmMain.PicBlatt(1).Height Then
      Call BlattNew
    End If
    ' Aktuelle Zeichenposition setzen
    FrmMain.PicBlatt(1).CurrentX = CurX
    FrmMain.PicBlatt(1).CurrentY = CurY
    ' Aktuelles Zeichen detektieren
    If AktChar = Chr$(27) Then
      ' ESC-Zeichen erkannt
      Select Case Mid$(Inhalt, AktPos + 1, 1)
        Case "*":  ' Grafik
          BlockLen = 0
          ' *-Typ decodieren (HP500C?)
          CmdTyp = "UnBek"
          If Mid$(Inhalt, AktPos + 2, 6) = "b0m80W" Then CmdTyp = 
"BMPImgH"
          If (Asc(Mid$(Inhalt, AktPos + 4, 1)) * &HFF + _
              Asc(Mid$(Inhalt, AktPos + 3, 1))) _
              <= 640 Then CmdTyp = "BMPImgV"
          If Mid$(Inhalt, AktPos + 2, 4) = "r01A" Then CmdTyp = "r01A"
          If Mid$(Inhalt, AktPos + 2, 5) = "rbc0U" Then CmdTyp = "rbc0U"
          If Mid$(Inhalt, AktPos + 2, 5) = "r640S" Then CmdTyp = "r640S"
          If Mid$(Inhalt, AktPos + 2, 5) = "r0q1A" Then CmdTyp = "r0q1A"
          If Mid$(Inhalt, AktPos + 2, 3) = "rbC" Then CmdTyp = "rbC"
          If Mid$(Inhalt, AktPos + 2, 5) = "t100R" Then CmdTyp = "t100R"
          If Mid$(Inhalt, AktPos + 2, 3) = "p2N" Then CmdTyp = "p2N"
          ' erkannten Typ zerlegen
          Select Case CmdTyp
            Case "BMPImgH": ' Horizontale BMP
              ' Header lesen
              GrLength = PixelX / 8
              GrDaten = Mid$(Inhalt, AktPos + 8, GrLength + 2)
              PosEoG = InStrRev(GrDaten, Chr$(&HD) & Chr(&H1B))
              If PosEoG > 0 Then
                GrLength = PosEoG - 1
              End If
              If AktPos + 8 + GrLength > Len(Inhalt) Then
                GrLength = Len(Inhalt) - 8 - AktPos
              End If
              ' Daten lesen
              'If (RowCount Mod 6) <> 5 Then
                For GrByteNr = 1 To GrLength
                  GrByte = Asc(Mid$(GrDaten, GrByteNr, 1))
                  'If (RowCount Mod 6) = 5 Then
                  '  FrmMain.PicBlatt(1).ForeColor = RGB(128, 0, 0)
                  'End If
                  Call BlattPointByteH(GrByte)
                Next GrByteNr
                CurY = CurY + PixelY
              'End If
              CurX = 0
              BlockLen = 7 + GrLength + 1
              RowCount = RowCount + 1
              FrmMain.PicBlatt(1).ForeColor = RGB(0, 0, 0)
            Case "BMPImgV": ' Vertikale BMP
              GrLength = Asc(Mid$(Inhalt, AktPos + 4, 1)) * &HFF + _
                         Asc(Mid$(Inhalt, AktPos + 3, 1))
              If AktPos + 4 + GrLength > Len(Inhalt) Then
                GrLength = Len(Inhalt) - 4 - AktPos
              End If
              GrDaten = Mid$(Inhalt, AktPos + 5, GrLength)
              ' Daten lesen
              For GrByteNr = 1 To GrLength
                GrByte = Asc(Mid$(GrDaten, GrByteNr, 1))
                Call BlattPointByteV(GrByte)
              Next GrByteNr
              CurX = 0
              CurY = CurY + 8
              BlockLen = 6 + GrLength + 2
            Case "r01A":  ' Grafik ab Cursorposition
              PixelY = 1
              BlockLen = 5
            Case "rbc0U":
              BlockLen = 6
            Case "r640S": ' Anzahl der Pixel = 640
              PixelX = 640
              BlockLen = 6
            Case "r0q1A":
              BlockLen = 6
            Case "rbC":   ' Grafikoff
              RowCount = 0
              BlockLen = 4
            Case "t100R": ' Auflösung = 100 dpi
              BlockLen = 6
            Case "p2N":
              BlockLen = 4
            Case Else:
              MsgBox Mid$(Inhalt, AktPos + 1, 20)
          End Select
        Case "=": ' Half LineFeed
          CurY = CurY + 4
          BlockLen = 1
        Case "l":
          BlockLen = 2
        Case "3": ' Zeilenabstand n/180 Zoll
          BlockLen = 2
        Case "2": ' Zeilenabstand 1/6 Zoll
          BlockLen = 1
        Case "W":
          BlockLen = 2
        Case "E": ' Reset defaults
          FrmMain.PicBlatt(1).Font.Bold = True
          BlockLen = 1
        Case "F": ' Fettdruck aus
          FrmMain.PicBlatt(1).Font.Bold = False
          BlockLen = 1
        Case "4": ' Kursivdruck ein
          FrmMain.PicBlatt(1).Font.Italic = True
          BlockLen = 1
        Case "5": ' Kursivdruck aus
          FrmMain.PicBlatt(1).Font.Italic = False
          BlockLen = 1
        Case "P": ' 10,5 Punkte, 10 cpi auswählen
          BlockLen = 1
        Case "&": ' ? Benutzerdefiniertes Zeichen festlegen ?
          CmdTyp = "UnBek"
          If Mid$(Inhalt, AktPos + 2, 10) = "a+180v720H" Then CmdTyp = 
"a+180v720H"
          If Mid$(Inhalt, AktPos + 2, 4) = "l26A" Then CmdTyp = "l26A"
          If Mid$(Inhalt, AktPos + 2, 4) = "a12L" Then CmdTyp = "a12L"
          If Mid$(Inhalt, AktPos + 2, 3) = "k6W" Then CmdTyp = "k6W"
          Select Case CmdTyp
            Case "a+180v720H":
              BlockLen = 11
            Case "l26A":
              BlockLen = 5
            Case "a12L": ' Left margin = 12 colums
              BlockLen = 5
            Case "k6W":
              BlockLen = 4
            Case Else:
              MsgBox Mid$(Inhalt, AktPos + 1, 20)
              BlockLen = 0
          End Select
        Case "(": ' HP-typische Kommandos
          CmdTyp = "UnBek"
          If Mid$(Inhalt, AktPos + 2, 3) = "s0B" Then CmdTyp = "s0B"
          If Mid$(Inhalt, AktPos + 2, 3) = "s3B" Then CmdTyp = "s3B"
          If Mid$(Inhalt, AktPos + 2, 4) = "s12H" Then CmdTyp = "s12H"
          If Mid$(Inhalt, AktPos + 2, 3) = "s6H" Then CmdTyp = "s6H"
          If Mid$(Inhalt, AktPos + 2, 2) = "0U" Then CmdTyp = "0U"
          If Mid$(Inhalt, AktPos + 2, 3) = "s6T" Then CmdTyp = "s6T"
          Select Case CmdTyp
            Case "s0B":  ' Bold = off
              FrmMain.PicBlatt(1).Font.Bold = False
              BlockLen = 4
            Case "s3B":  ' Bold = on
              FrmMain.PicBlatt(1).Font.Bold = True
              BlockLen = 4
            Case "s12H": ' Pitch = 12 cpi on
              BlockLen = 5
            Case "s6H":
              BlockLen = 4
            Case "0U":
              BlockLen = 3
            Case "s6T":
              BlockLen = 4
            Case Else:
              MsgBox Mid$(Inhalt, AktPos + 1, 20)
              BlockLen = 0
          End Select
        Case ")": ' HP-typische Kommandos
          CmdTyp = "UnBek"
          If Mid$(Inhalt, AktPos + 2, 3) = "s0B" Then CmdTyp = "s0B"
          If Mid$(Inhalt, AktPos + 2, 4) = "s12H" Then CmdTyp = "s12H"
          If Mid$(Inhalt, AktPos + 2, 3) = "s6H" Then CmdTyp = "s6H"
          If Mid$(Inhalt, AktPos + 2, 2) = "0U" Then CmdTyp = "0U"
          If Mid$(Inhalt, AktPos + 2, 3) = "s6T" Then CmdTyp = "s6T"
          Select Case CmdTyp
            Case "s0B":  ' Stroke weight = Medium off
              BlockLen = 4
            Case "s12H": ' Pitch = 12 cpi off
              BlockLen = 5
            Case "s6H":
              BlockLen = 4
            Case "0U":
              BlockLen = 3
            Case "s6T":
              BlockLen = 4
            Case Else:
              MsgBox Mid$(Inhalt, AktPos + 1, 20)
              BlockLen = 0
          End Select
        Case Else:
          MsgBox Mid$(Inhalt, AktPos + 1, 20)
          BlockLen = 0
      End Select
      AktPos = AktPos + BlockLen
    Else
      ' typisches Zeichen
      With FrmMain.PicBlatt(1)
        AktVal = Asc(AktChar)
        Select Case AktVal
          Case 10:        ' LF (Line Feed)
            CurY = CurY + FrmMain.PicBlatt(1).Font.Size
          Case 12:        ' FF (Form Feed)
            If AktPos > 1 Then Call BlattNew
          Case 13:        ' CR (Carriage Return)
            CurX = 0
          Case Is >= 32:  ' normales ASCII-Zeichen
            FrmMain.PicBlatt(1).Print AktChar;
            CurX = CurX + FrmMain.PicBlatt(1).Font.Size - 2
            If CurX > 640 Then
              CurX = 0
              CurY = CurY + FrmMain.PicBlatt(1).Font.Size - 2
            End If
        End Select
      End With
    End If
    DoEvents
  Next AktPos
  Call BlattNew
End Sub

Sub BlattNew()
  ' Bild umkopieren
  FrmMain.PicBlatt(0).Cls
  Call SetStretchBltMode(FrmMain.PicBlatt(0).hdc, HALFTONE)
  Call StretchBlt(FrmMain.PicBlatt(0).hdc, 0, 0, 
FrmMain.PicBlatt(0).Width, FrmMain.PicBlatt(0).Height, 
FrmMain.PicBlatt(1).hdc, 0, 0, FrmMain.PicBlatt(1).Width, 
FrmMain.PicBlatt(1).Height, vbSrcCopy)
  SeiteNr = SeiteNr + 1
  FrmMain.LblInfo.Caption = "Seite: " & SeiteNr
  FrmMain.CboSeite.AddItem FrmMain.LblInfo.Caption
  FrmMain.CboSeite = FrmMain.LblInfo.Caption
  FrmMain.CboSeite.Enabled = True
  If SeiteNr <= 40 Then
    SavePicture FrmMain.PicBlatt(1).Image, App.Path & "\Seite_" & 
CStr(SeiteNr) & ".bmp"
  End If
  FrmMain.PicBlatt(1).Cls
  CurX = 0
  CurY = 0
End Sub

' 
************************************************************************ 
******
' Grafik-Routinen
' 
************************************************************************ 
******

Sub BlattPointByteV(ByVal ByteWert As Byte)
  FrmMain.PicBlatt(1).Line (CurX, CurY)-(CurX, CurY + 8), RGB(240, 240, 
240)
  If (ByteWert And &H1) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX, CurY + 
7), RGB(0, 0, 0)
  If (ByteWert And &H2) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX, CurY + 
6), RGB(0, 0, 0)
  If (ByteWert And &H4) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX, CurY + 
5), RGB(0, 0, 0)
  If (ByteWert And &H8) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX, CurY + 
4), RGB(0, 0, 0)
  If (ByteWert And &H10) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX, CurY 
+ 3), RGB(0, 0, 0)
  If (ByteWert And &H20) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX, CurY 
+ 2), RGB(0, 0, 0)
  If (ByteWert And &H40) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX, CurY 
+ 1), RGB(0, 0, 0)
  If (ByteWert And &H80) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX, CurY 
+ 0), RGB(0, 0, 0)
  CurX = CurX + 1
End Sub

Sub BlattPointByteH(ByVal ByteWert As Byte)
  FrmMain.PicBlatt(1).Line (CurX, CurY)-(CurX + 8, CurY), RGB(240, 240, 
240)
  If (ByteWert And &H1) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX + 7, 
CurY), RGB(0, 0, 0)
  If (ByteWert And &H2) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX + 6, 
CurY), RGB(0, 0, 0)
  If (ByteWert And &H4) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX + 5, 
CurY), RGB(0, 0, 0)
  If (ByteWert And &H8) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX + 4, 
CurY), RGB(0, 0, 0)
  If (ByteWert And &H10) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX + 3, 
CurY), RGB(0, 0, 0)
  If (ByteWert And &H20) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX + 2, 
CurY), RGB(0, 0, 0)
  If (ByteWert And &H40) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX + 1, 
CurY), RGB(0, 0, 0)
  If (ByteWert And &H80) <> 0 Then FrmMain.PicBlatt(1).PSet (CurX + 0, 
CurY), RGB(0, 0, 0)
  CurX = CurX + 8
End Sub

Grüße Nachos

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.