Drukarki paragonowe

Pozostałe układy mikrokontrolerów, układy peryferyjne i inne, nie mieszczące się w powyższych kategoriach.
Awatar użytkownika
gaweł
Expert
Expert
Posty: 657
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Drukarki paragonowe

Postautor: gaweł » sobota 02 lut 2019, 23:41

Drukarki w świecie mikrokontrolerów
Myszka-60


Elementy technologii żółtych kredensów
prn01_ilu00.jpg


Zdarza się czasami, że coś trzeba wydrukować spod procka. Najprostszym rozwiązaniem jest zastosowanie drukarki termicznej z papierem „z rolki”. Drukarki te są przyłączane do czegokolwiek poprzez interfejs szeregowy RS232. Przykładem takiego rozwiązania jest polska drukarka MYSZKA-60. To, że jest „polska” automatycznie oznacza, że drukuje również polskie literki. Ta drukarka umożliwia również wydruk kodów kreskowych. Również dysponuje obcinarką do wydruków sterowaną programowo, można na zakończenie wydruku zażądać odcięcia papieru (tak trochę to "krzywo" działa, bo konieczne jest wydrukowanie przynajmniej 3 pustych wierszy przed obcięciem, bo inaczej wydruk będzie niekompletny).
Jej możliwości najlepiej zaprezentować pokazując wydruk jej autotestu (pokazuje kroje czcionek i inne bajery) jak na poniższych fotografiach:
prn01_ilu01.jpg
prn01_ilu02.jpg
prn01_ilu03.jpg
Ciekawostką jest, i pewną zagwozdką zarazem, że na wydruku jest coś na temat DIPSWICH, natomiast fizycznie jakoś go nie znalazłem. Znaczy w tym egzemplarzu nie znalazłem, natomiast pamiętam z czasów opracowywania „żółtych kredensów”, że takie były. No cóż jest, jak jest. Nie oceniam i nie wnikam (może to jakaś późniejsza wersja trochę okrojona, tak jakoś mi się zawieruszyła).
Kilka widoków na sprzęcior:
prn01_ilu04.jpg
prn01_ilu05.jpg
prn01_ilu06.jpg
Trochę mnie dziwi rozwiązanie złącza w samej drukarce. W moim przekonaniu powinno być damskie, wtedy da się użyć typowy kabelek RS232, a tak trzeba takowy dorobić. W sumie nic trudnego, wystarczy 3-żyłowy kawałek kabelka na linie (z punktu widzenia jakiegoś systemu prockowego lub normalnego kompa): TxD – dane nadawane, DTR – linia modemowa do sygnalizacji, że skończył się papier i GND – masa. Łatwo zauważyć, że drukarka nic nie nadaje, nie ma linii RxD (z punktu widzenia jakiego systemu prockowego).
Schemat środowiska badawczego, w istotnym fragmencie, pokazują poniższe rysunki.
prn01_ilu07.png
Jest to jednostka centralna jakiegoś układu zawierająca procka LPC2368 (w sumie jest mało istotne jaki to procek, wybór padł na ten, bo w tym procku jest pełnomodemowy UART → UART1). Można użyć w sumie dowolnego, jak kontroler nie posiada obsługi linii modemowych, to zawsze takie można zasymulować na normalnych pinach. Więc powyższy procek jest napędzany kwarcem 12MHz, z wewnętrzną obsługą PLL'a. Procek jest programowany w układzie przez dedykowany interfejsik (właściwie to on nic nie zawiera, ma drugi układ ST3232). Przyłączony do proca pełnomodemowy interfejs jest pokazany poniżej.
prn01_ilu08.png
Dodatkowe kanały szeregowe (UART0 i UART2), już bez linii modemowych, bo ich nie ma wychodzą, na świat przez układ ST3232.
Tyle w kwestii hardware. Układ badawczy jest następujący:
prn01_ilu09.jpg
i z przypiętą drukarką.
prn01_ilu10.jpg
Teraz soft.
Drukarka ma polskie litery, których kody odbiegają od tych stosowanych w windoze, więc konieczne jest przekodowanie.
Drukarka wisi na UART1, przez UART2 jest połączenie z terminalem (emulatorem terminala). Z niego można zapodać coś do wydruku. Rozwiązanie jest podobne do stosowanego w „żółtych kredensach”. Tam strumień danych pochodził z sieci, tu zapodaję via serial. Transmitowane dane są identyczne (to znaczy zależy od wersji kredensów, bo tego było wiele, wraz z ewolucją sprzętową kredensów, soft również ulegał ewolucji, właściwie to nic nadzwyczajnego, zawsze jak coś się ulepsza, to i okolice mają fajniej). To rozwiązanie dotyczy pierwszych kredensów.
Dane do wydruku zapodawane były tekstowo. Każdy wiersz poprzedzony był sygnaturą, oznaczająca „a o co chodzi?”. Było to polecenie otwarcia wydruku, dane do wydruku oraz informacja o zamknięciu wydruku. Same dane miały kilka możliwości, można było dane zapodać z kodowaniem w UTF-8 lub w ANSI (no i dodatkowo możliwość druku kodu kreskowego). Normalnie kredensy same z siebie używały kodowania polskich znaków w ANSI, ale jak coś przyszło via WEBSERWICE, bo kredens był na takiej smyczy połączony do centrali, to tam dane chodziły w UTF-8.
Sygnatury są następujące:
[o] – otwarcie dokumentu
[O] – otwarcie dokumentu
[d]dane – wydruk danych tekstowych kodowanych w ANSI,
[D]dane – wydruk danych tekstowych kodowanych w UTF-8,
[b]tekst – wydruk w kodzie kreskowym
[B]tekst – wydruk w kodzie kreskowym
[c] – zamkniecie dokumentu
[C] – zamknięcie dokumentu.

Obsługa strumienia wygląda mniej więcej tak:

Kod: Zaznacz cały

#include "prndriver.h"
#include "uart1.h"
#include "serialconst.h"

#define CR                      0x0D
#define LF                      0x0A
#define ESC                     0x1B

#define CharCodePlSmaLetA       0xB9
#define CharCodePlSmaLetC       0xE6
#define CharCodePlSmaLetE       0xEA
#define CharCodePlSmaLetL       0xB3
#define CharCodePlSmaLetN       0xF1
#define CharCodePlSmaLetO       0xF3
#define CharCodePlSmaLetS       0x9C
#define CharCodePlSmaLetZy      0xBF
#define CharCodePlSmaLetZi      0x9F
#define CharCodePlBigLetA       0xA5
#define CharCodePlBigLetC       0xC6
#define CharCodePlBigLetE       0xCA
#define CharCodePlBigLetL       0xA3
#define CharCodePlBigLetN       0xD1
#define CharCodePlBigLetO       0xD3
#define CharCodePlBigLetS       0x8C
#define CharCodePlBigLetZy      0xAF
#define CharCodePlBigLetZi      0x8F

#define PrinterPlSmaLetA        0xA5
#define PrinterPlSmaLetC        0x86
#define PrinterPlSmaLetE        0xA9
#define PrinterPlSmaLetL        0x88
#define PrinterPlSmaLetN        0xE4
#define PrinterPlSmaLetO        0xA2
#define PrinterPlSmaLetS        0x98
#define PrinterPlSmaLetZy       0xBE
#define PrinterPlSmaLetZi       0xAB
#define PrinterPlBigLetA        0xA4
#define PrinterPlBigLetC        0x8F
#define PrinterPlBigLetE        0xA8
#define PrinterPlBigLetL        0x9D
#define PrinterPlBigLetN        0xE3
#define PrinterPlBigLetO        0xE0
#define PrinterPlBigLetS        0x97
#define PrinterPlBigLetZy       0xBD
#define PrinterPlBigLetZi       0x8D

#define CommandBufferSize       63
typedef struct {
         PrinterServiceProcType   PrinterReadyService ;
         PrinterServiceProcType   PrinterNotReadyService ;
         UCHAR                    CommandBuffer [ CommandBufferSize + 1 ] ;
         USHORT                   BufferSize ;
         USHORT                   Index ;
         UCHAR                    DocumentIsOpened ;
         UCHAR                    PrinterIsReady ;
       } PrinterInstanceRecT ;

typedef struct {
                 UCHAR             InpCode ;
                 UCHAR             OutCode ;
               } EncryptionTableElementType ;
typedef EncryptionTableElementType EncryptionTableType [ 18 ] ;

typedef enum { OpenDocumentOption    ,
               DataAnsiOption        ,
               DataUTF8Option        ,
               BarCodeOption         ,
               CloseDocumentOption   ,
               UnknownOption         } CommandOptionType ;

static PrinterInstanceRecT PrinterInstance ;
 
 
static CommandOptionType SelectCommand ( void )
{
  /*-------------------------------------------------------------------------*/
  if ( PrinterInstance . CommandBuffer [ 0 ] != '[' )
    return UnknownOption ;
  if ( PrinterInstance . CommandBuffer [ 2 ] != ']' )
    return UnknownOption ;
  switch ( PrinterInstance . CommandBuffer [ 1 ] )
  {
    case 'o' :
    case 'O' :
      return OpenDocumentOption ;
    case 'd' :
      return DataAnsiOption ;
    case 'D' :
      return DataUTF8Option ;
    case 'b' :
    case 'B' :
      return BarCodeOption ;
    case 'c' :
    case 'C' :
      return CloseDocumentOption ;
  } /* switch */ ;
  return UnknownOption ;
} /* SelectCommand */


static void RewindPrinterBuffer ( void )
{
  /*-------------------------------------------------------------------------*/
  PrinterInstance . BufferSize = 0 ;
  PrinterInstance . CommandBuffer [ 0 ] = 0 ;
} /* RewindPrinterBuffer */


static const EncryptionTableType LatinEncryptionTable = {
       { CharCodePlSmaLetA      , 'a' } ,
       { CharCodePlSmaLetC      , 'c' } ,
       { CharCodePlSmaLetE      , 'e' } ,
       { CharCodePlSmaLetL      , 'l' } ,
       { CharCodePlSmaLetN      , 'n' } ,
       { CharCodePlSmaLetO      , 'o' } ,
       { CharCodePlSmaLetS      , 's' } ,
       { CharCodePlSmaLetZy     , 'z' } ,
       { CharCodePlSmaLetZi     , 'z' } ,
       { CharCodePlBigLetA      , 'A' } ,
       { CharCodePlBigLetC      , 'C' } ,
       { CharCodePlBigLetE      , 'E' } ,
       { CharCodePlBigLetL      , 'L' } ,
       { CharCodePlBigLetN      , 'N' } ,
       { CharCodePlBigLetO      , 'O' } ,
       { CharCodePlBigLetS      , 'S' } ,
       { CharCodePlBigLetZy     , 'Z' } ,
       { CharCodePlBigLetZi     , 'Z' } } ;

static char LatinTranscription ( char Ch )
{
  USHORT Loop ;
  const EncryptionTableElementType * Element ;
  /*-------------------------------------------------------------------------*/
  Element = LatinEncryptionTable ;
  for ( Loop = 0 ; Loop < 18 ; Loop ++ )
  {
    if ( Element -> InpCode == Ch )
      return Element -> OutCode ;
    Element ++ ;
  } /* for */ ;
  return Ch ;
} /* LatinTranscription */


static const EncryptionTableType AnsiEncryptionTable =
          { { CharCodePlSmaLetA      , PrinterPlSmaLetA   } ,
            { CharCodePlSmaLetC      , PrinterPlSmaLetC   } ,
            { CharCodePlSmaLetE      , PrinterPlSmaLetE   } ,
            { CharCodePlSmaLetL      , PrinterPlSmaLetL   } ,
            { CharCodePlSmaLetN      , PrinterPlSmaLetN   } ,
            { CharCodePlSmaLetO      , PrinterPlSmaLetO   } ,
            { CharCodePlSmaLetS      , PrinterPlSmaLetS   } ,
            { CharCodePlSmaLetZy     , PrinterPlSmaLetZy  } ,
            { CharCodePlSmaLetZi     , PrinterPlSmaLetZi  } ,
            { CharCodePlBigLetA      , PrinterPlBigLetA   } ,
            { CharCodePlBigLetC      , PrinterPlBigLetC   } ,
            { CharCodePlBigLetE      , PrinterPlBigLetE   } ,
            { CharCodePlBigLetL      , PrinterPlBigLetL   } ,
            { CharCodePlBigLetN      , PrinterPlBigLetN   } ,
            { CharCodePlBigLetO      , PrinterPlBigLetO   } ,
            { CharCodePlBigLetS      , PrinterPlBigLetS   } ,
            { CharCodePlBigLetZy     , PrinterPlBigLetZy  } ,
            { CharCodePlBigLetZi     , PrinterPlBigLetZi  } } ;

static char PLTranscription ( char Ch )
{
  USHORT Loop ;
  const EncryptionTableElementType * Element ;
  /*-------------------------------------------------------------------------*/
  Element = AnsiEncryptionTable ;
  for ( Loop = 0 ; Loop < 18 ; Loop ++ )
  {
    if ( Element -> InpCode == Ch )
      return Element -> OutCode ;
    Element ++ ;
  } /* for */ ;
  return Ch ;
} /* PLTranscription */


static void CutPaper ( void )
{
  /*-------------------------------------------------------------------------*/
  UART1Send ( ESC ) ;
  UART1Send ( 'i' ) ;
} /* CutPaper */


static void LineFeed ( void )
{
  /*-------------------------------------------------------------------------*/
  UART1Send ( CR ) ;
  UART1Send ( LF ) ;
} /* LineFeed */


static void PrintAnsiEncoding ( void )
{
  UCHAR * PCh ;
  /*-------------------------------------------------------------------------*/
  PCh = PrinterInstance . CommandBuffer + 3 ;
  while ( * PCh )
  {
    UART1Send ( PLTranscription ( * PCh ) ) ;
    PCh ++ ;
  } /* while */ ;
  LineFeed ( ) ;
} /* PrintAnsiEncoding */


static UCHAR GetNextChar ( void )
{
  UCHAR CurrentChar ;
// Pl UTF-8 char code 
//  0xC4  0x84   A z ogonkiem
//  0xC4  0x85   a z ogonkiem
//  0xC4  0x86   C z kreska
//  0xC4  0x87   c z kreska
//  0xC4  0x98   E z ogonkiem
//  0xC4  0x99   e z ogonkiem
//  0xC5  0x81   L z kreska
//  0xC5  0x82   l z kreska
//  0xC5  0x83   N z kreska
//  0xC5  0x84   n z kreska
//  0xC3  0x93   O z kreska
//  0xC3  0xB3   o z kreska
//  0xC5  0x9A   S z kreska
//  0xC5  0x9B   S z kreska
//  0xC5  0xB9   Z z kreska
//  0xC5  0xBA   z z kreska
//  0xC5  0xBB   Z z kropka
//  0xC5  0xBC   z z kropka
  /*-------------------------------------------------------------------------*/
  CurrentChar = PrinterInstance.CommandBuffer[PrinterInstance.Index++] ;
  if ( CurrentChar == 0xC3 )
  {
    CurrentChar = PrinterInstance.CommandBuffer[PrinterInstance.Index++] ;
    if ( CurrentChar == 0x93 )
      return ( PrinterPlBigLetO ) ;
    if ( CurrentChar == 0xB3 )
      return ( PrinterPlSmaLetO ) ;
    return ' ' ;
  } /* if ... */
  else
  {
    if ( CurrentChar == 0xC4 )
    {
      CurrentChar = PrinterInstance.CommandBuffer[PrinterInstance.Index++] ;
      switch ( CurrentChar )
      {
        case 0x84 :
          return PrinterPlBigLetA ;
        case 0x85 :
          return PrinterPlSmaLetA ;
        case 0x86 :
          return PrinterPlBigLetC ;
        case 0x87 :
          return PrinterPlSmaLetC ;
        case 0x98 :
          return PrinterPlBigLetE ;
        case 0x99 :
          return PrinterPlSmaLetE ;
      } /* switch */ ;
      return ' ' ;
    } /* if ... */
    else
    {
      if ( CurrentChar == 0xC5 )
      {
        CurrentChar = PrinterInstance.CommandBuffer[PrinterInstance.Index++] ;
        switch ( CurrentChar )
        {
          case 0x81 :
            return PrinterPlBigLetL ;
          case 0x82 :
            return PrinterPlSmaLetL ;
          case 0x83 :
            return PrinterPlBigLetN ;
          case 0x84 :
            return PrinterPlSmaLetN ;
          case 0x9A :
            return PrinterPlBigLetS ;
          case 0x9B :
            return PrinterPlSmaLetS ;
          case 0xB9 :
            return PrinterPlBigLetZi ;
          case 0xBA :
            return PrinterPlSmaLetZi ;
          case 0xBB :
            return PrinterPlBigLetZy ;
          case 0xBC :
            return PrinterPlSmaLetZy ;
        } /* switch */ ;
        return ' ' ;
      } /* if ... else */ ;
    } /* if ... else */ ;
  } /* if ... else */ ;
  return CurrentChar ;
} /* GetNextChar */


static void PrintUTF8Encoding ( void )
{
  UCHAR Ch ;
  /*-------------------------------------------------------------------------*/
  PrinterInstance . Index = 3 ;
  for ( ; ; )
  {
    Ch = GetNextChar ( ) ;
    if ( ! Ch )
      break ;
    UART1Send ( Ch ) ;
  } /* for */ ;
  LineFeed ( ) ;
} /* PrintUTF8Encoding */


static void PrintBarCode ( void )
{
  UCHAR * PCh ;
  UCHAR StringSize ;
  /*-------------------------------------------------------------------------*/
  UART1Send ( ESC ) ;
  UART1Send ( 'P' ) ;
  PCh = PrinterInstance . CommandBuffer + 3 ;
  StringSize = 0 ;
  while ( * PCh )
  {
    StringSize ++ ;
    PCh ++ ;
  } /* while */ ;
  UART1Send ( StringSize ) ;
  PCh = PrinterInstance . CommandBuffer + 3 ;
  while ( * PCh )
  {
    UART1Send ( LatinTranscription ( * PCh ) ) ;
    PCh ++ ;
  } /* while */ ;
} /* PrintBarCode */


static void PrintLine ( void )
{
  /*-------------------------------------------------------------------------*/
  if ( PrinterInstance . BufferSize >= 3 )
  {
    if ( PrinterInstance . PrinterIsReady )
    {
      if ( ! CheckPrinterOperable ( ) )
      {
        if ( PrinterInstance . PrinterNotReadyService )
          PrinterInstance . PrinterNotReadyService ( ) ;
        PrinterInstance . PrinterIsReady = FALSE ;
      } /* if */ ;
    } /* if ... */
    else
    {
      if ( CheckPrinterOperable ( ) )
      {
        if ( PrinterInstance . PrinterReadyService )
          PrinterInstance . PrinterReadyService ( ) ;
        PrinterInstance . PrinterIsReady = TRUE ;
      } /* if */ ;
    } /* if ... else */ ;
    if ( PrinterInstance . PrinterIsReady )
    {
      switch ( SelectCommand ( ) )
      {
        case OpenDocumentOption :
          PrinterInstance . DocumentIsOpened = TRUE ;
          break ;
        case DataAnsiOption :
          if ( PrinterInstance . DocumentIsOpened )
            PrintAnsiEncoding ( ) ;
          break ;
        case DataUTF8Option :
          if ( PrinterInstance . DocumentIsOpened )
            PrintUTF8Encoding ( ) ;
          break ;
        case BarCodeOption :
          if ( PrinterInstance . DocumentIsOpened )
            PrintBarCode ( ) ;
          break ;
        case CloseDocumentOption :
          if ( PrinterInstance . DocumentIsOpened )
          {
            LineFeed ( ) ;
            LineFeed ( ) ;
            LineFeed ( ) ;
            CutPaper ( ) ;
          } /* if */ ;
          PrinterInstance . DocumentIsOpened = FALSE ;
          break ;
        case UnknownOption :
          break ;
      } /* switch */ ;
      RewindPrinterBuffer ( ) ;
    } /* if */ ;
  } /* if */ ;
} /* PrintLine */


void ProcessChar ( UCHAR Ch )
{
  /*-------------------------------------------------------------------------*/
  if ( Ch < ' ' )
  {
    if ( Ch == CR )
      PrintLine ( ) ;
  } /* if ... */
  else
  {
    if ( PrinterInstance . BufferSize < CommandBufferSize )
    {
        PrinterInstance . CommandBuffer [ PrinterInstance . BufferSize ] = Ch ;
        PrinterInstance . BufferSize ++ ;
        PrinterInstance . CommandBuffer [ PrinterInstance . BufferSize ] = 0 ;
    } /* if */ ;
  } /* if ... else */ ;
} /* ProcessChar */


UCHAR CheckPrinterOperable ( void )
{
  UCHAR ModemStatus ;
  /*-------------------------------------------------------------------------*/
  ModemStatus = GetInputModemLine ( ) ;
  if ( ModemStatus & DSRControlUARTCode )
    return TRUE ;
  return FALSE ;
} /* CheckPrinterOperable */


void SetPrinterNotify ( PrinterServiceProcType NotReadyNotify ,
                        PrinterServiceProcType ReadyNotify )
{
  /*-------------------------------------------------------------------------*/
  PrinterInstance . PrinterReadyService = ReadyNotify ;
  PrinterInstance . PrinterNotReadyService = NotReadyNotify ;
} /* SetPrinterNotify */


void InitPrinterService ( void )
{
  /*-------------------------------------------------------------------------*/
  RewindPrinterBuffer ( ) ;
  PrinterInstance . DocumentIsOpened = FALSE ;
  PrinterInstance . PrinterIsReady = CheckPrinterOperable ( ) ;
  PrinterInstance . PrinterReadyService = ( PrinterServiceProcType ) 0 ;
  PrinterInstance . PrinterNotReadyService = ( PrinterServiceProcType ) 0 ;
} /* InitPrinterService */
Program do obsługi drukarki, może być następujący:

Kod: Zaznacz cały

#include <LPC23xx.H>
#include "system.h"
#include "types.h"
#include "irqvectors.h"
#include "serialconst.h"
#include "uart1.h"
#include "uart2.h"
#include "prndriver.h"

#define IRQCallCntLimit                 500

static ULONG IRQCallCounter ;

static void SoftwareInit ( void )
{
  /*-------------------------------------------------------------------------*/
  IRQCallCounter = 0 ;
  InitPrinterService ( ) ;
} /* SoftwareInit */


static __irq void T1_IRQHandler ( void )
{
  /*-------------------------------------------------------------------------*/
  IRQCallCounter ++ ;
  if ( IRQCallCounter >= IRQCallCntLimit )
  {
    IRQCallCounter = 0 ;
  } /* if */ ;
  T1IR = 1 ;
  VICVectAddr = 0 ;
} /* T1_IRQHandler */


static void HardwareInit ( void )
{
  /*-------------------------------------------------------------------------*/
  PINSEL10 = 0 ;
  T1MR0 = ( PCLK / 1000 ) - 1 ;
  T1MCR = 3 ;
  T1TCR = 1 ;
  VICVectAddr5 = ( unsigned long ) T1_IRQHandler ;
  VICVectCntl5 = 15 ;
  VICIntEnable = ( 1 << TIMER1_Interrupt ) ;
  UART1InitEnvir ( ) ;
  UART2InitEnvir ( ) ;
} /* HardwareInit */


UCHAR Hello1 [ ]         = "\r\nWitaj koles przy kompie\r\n\r\n[o] - otwarcie dokumentu\r\n[d]dane - wydruk danych tekstowych\r\n[b]liczba - wydruk liczby w kodzie kreskowym\r\n[c] - zamkniecie dokumentu\r\n\r\nNapisz cos:\r\n" ;
UCHAR NoPaperMessage [ ] = "\r\nWloz papier do drukarki\r\n" ;
UCHAR PaperOKMessage [ ] = "\r\nPapier juz jest OK\r\n" ;

static void HelloMessage ( void )
{
  /*-------------------------------------------------------------------------*/
  UART2SendString ( Hello1 ) ;
} /* HelloMessage */


void NoPaper ( void )
{
  /*-------------------------------------------------------------------------*/
  UART2SendString ( NoPaperMessage ) ;
} /* NoPaper */


void PaperOK ( void )
{
  /*-------------------------------------------------------------------------*/
  UART2SendString ( PaperOKMessage ) ;
} /* PaperOK */


int main ( void )
{
  /*-------------------------------------------------------------------------*/
  SysInit ( ) ;
  HardwareInit ( )  ;
  SoftwareInit ( ) ;
  UART1HardwInit( FOSC , N81Mode , 9600 ) ;
  UART2HardwInit( FOSC , N81Mode , 9600 ) ;
  HelloMessage ( ) ;
  if ( ! CheckPrinterOperable ( ) )
    NoPaper ( ) ;
  SetPrinterNotify ( NoPaper , PaperOK ) ;
  for ( ; ; )
  {
    if ( UART2DataPresent ( ) )
      ProcessChar ( UART2GetData ( ) ) ;
  } /* loop */ ;
} /* main */
Do obsługi drukarki „podłącza się” dwie funkcje SetPrinterNotify(NoPaper,PaperOK) do sygnalizacji i reakcji na brak papieru w drukarce. Normalnie w sytuacji braku papieru, to strumień zachowywany był na dysku, by nic nie zaginęło. Tutaj to należałoby wstrzymać się z generowaniem wydruku, a przynajmniej poinformować o takowym zdarzeniu.
Nie chciało mi się „ręcznie za każdym razem wklepywać tego samego”, więc utworzyłem sobie mały pliczek, który był wysyłany via serial do procka armowego. Pliczek jest następujący:
[o]
[d]Witaj koles przy kompie
[d]
[d][o] - otwarcie dokumentu
[d][d]dane - wydruk danych tekstowych
[d][b]liczba - wydruk liczby w kodzie kreskowym
[d][c] - zamkniecie dokumentu
[b]123456789
[d]litera A, i a,: Ą i ą
[d]litera C' i c': Ć i ć
[d]litera E, i e,: Ę i ę
[d]litera L/ i l/: Ł i ł
[d]litera N' i n': Ń i ń
[d]litera O' i o': Ó i ó
[d]litera S' i s': Ś i ś
[d]litera Z- i z-: Ż i ż
[d]litera Z' i z': Ź i ź
[d]
[d]
[c]

Do komunikacji używam takiego programiku:
prn01_ilu11.PNG
gdzie po kliknięciu na „Send File” i wskazaniu właściwego pliczku, drukarka produkuje taki wydruczek.
prn01_ilu12.jpg
Drukarka, … jak drukarka, jest jaka jest. W następnych kredensach były lepsze, głównie z powodu adaptacji do innych alfabetów narodowych. Tu były tylko polskie, a z czasem stały się potrzebne inne, o czym wkrótce napiszę. To będą fajne drukarki od CUSTOM, mam dwa modele: TL60 i TG2460.

Kilka załączników:
KODY_STERUJACE_DRUKAREK_MYSZKA_60PU_60E.pdf
minimyszka_lc_3.pdf
myszka.7z
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse

Awatar użytkownika
PAMPKIN
Posty: 3
Rejestracja: poniedziałek 07 maja 2018, 08:35

Re: Drukarki paragonowe

Postautor: PAMPKIN » niedziela 03 lut 2019, 14:40

To mnie kolega zaintrygował (czekam na więcej), co do kodu znaków, to jest Latin-2 potwierdza to moja analogowa tablica.

IMG_20190203_142227.jpg
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Awatar użytkownika
gaweł
Expert
Expert
Posty: 657
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: Drukarki paragonowe

Postautor: gaweł » niedziela 03 lut 2019, 20:37

 
PAMPKIN pisze:To mnie kolega zaintrygował (czekam na więcej), co do kodu znaków, to jest Latin-2 potwierdza to moja analogowa tablica.

Zgadza się, jest o tym napisane w minimyszka_lc_3.pdf, nie napisałem o tym :shock: ? Cóż, przepraszam, jakoś wypadło mi z głowy... ;)

Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse

Awatar użytkownika
gaweł
Expert
Expert
Posty: 657
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: Drukarki paragonowe

Postautor: gaweł » piątek 15 lut 2019, 13:33

PAMPKIN pisze:To mnie kolega zaintrygował (czekam na więcej)

Bardzo proszę, realizacja zamówienia...

TL80

prn02_ilu00.jpg

Ciekawą propozycję drukarek są urządzenia oferowane przez CUSTOM. Są to również drukarki termiczne przyłączane do systemu za pośrednictwem łącza szeregowego.
Kilka fotek drukarskiego mistrza:
prn02_ilu01.jpg
prn02_ilu02.jpg
prn02_ilu03.jpg
Złącza drukarki, z istotnego punktu widzenia, zawierają wejścia zasilania oraz złącze szeregowe RS232 (w wariancie złącza RJ45).
prn02_ilu04.jpg
W tym przypadku, jak ktoś nie ma odpowiedniego kabelka, to można go sobie zdobyć samodzielnie. Nie jest to jakiś karkołomny wyczyn, w dokumentacji do drukarki jest podany „algorytm kabelka”.
prn02_ilu05.png
Odrobinka własnej pracy i... mamy sukces. Kawałek jakiegoś gotowego kabelka od ethernetu (ma już zakutą złączkę RJ45) i na drugim końcu klasyczny DSUB-9 żeński.
prn02_ilu06.jpg
Finał:
prn02_ilu07.jpg
Mając tak przygotowane środowisko, można zacząć zabawę. Do uzyskania jest wszystko, cokolwiek się zechce. Cały system umożliwia własną definicję czcionek i każdych innych znaków. Idea sprowadza się do modyfikacji pliku wsadu czcionek dla drukarki. W tym celu potrzebne są dwa programy, które można ściągnąć ze strony producenta: http://www.custom.biz. Na stronie głównej klikamy na
prn02_ilu08.png
Klikamy na obrazek drukarki (dla niepoznaki należy kliknąć na TG2460, co za ironia...).
prn02_ilu09.png
Prowadzi do
prn02_ilu10.png
Zjeżdżamy na dół strony do strefy DOWNLOAD.
prn02_ilu11.png
I wjeżdżamy na UTILITIES.
prn02_ilu12.png
Prowadzi to do „ogromnych możliwości” zabawy z maszynerią.
prn02_ilu13.png
Ściągamy dwa programy (będą to pliki typu ZIP, które należy rozpakować i zainstalować).
Jeden jest programem do modyfikacji czcionek, drugi jest programem do ładowania uzyskanych skarbów do drukarki.
Czcionki modyfikuje się następująco. Odpalamy FONTMAKE.
Otwieramy plik: File → Open *.psw.
Ja mam przygotowany już plik po modyfikacjach, więc go otwieram (TL60-polska.PSW).
prn02_ilu16.png
Program pyta, którą tabelę będziemy modyfikować. Należy wskazać numer 2.
prn02_ilu17.png
Klikając na znak w zielonym okienku, otwiera się do modyfikacji font (na przykładzie Ł). Posiłkując się „ołówkiem” można włączać/wyłączać pojedyncze pikseli.
prn02_ilu18.png
Można zmienić absolutnie wszystko, stworzyć własną wizję według własnego uznania, właściwie to limitem jest własna wyobraźnia. Plik (TL60-polska.PSW) zawiera wbite polskie literki o identycznych kodach jak poprzednio. Po zmianach plik należy zapisać jako *.PSW.
Teraz należy odpalić drugi program (UPGCEPRN).
prn02_ilu19.png
Klikając na Select *.PSW, otworzyć zmodyfikowany plik. Aktywują się kolejne przyciski do wykorzystania.
prn02_ilu20.png
Akcja rozpoczyna się po kliknięciu na Begin upgrade.
prn02_ilu21.png
Pozostało wskazać port szeregowy i …pojechało.
prn02_ilu22.png
Po zakończeniu mamy nową rzeczywistość drukarkową.

Dodatkowe materiały:
kody sterujące drukarką
DOMC-0021E.pdf
Dane techniczne
PCTL-60.pdf
Plik fontów drukarki
TL60-polska.zip
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse


Wróć do „Inne mikroklocki, również peryferyjne”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 1 gość