первый
This commit is contained in:
192
devices/Printers/ESC_POS/ESC_POS_Printer.cpp
Normal file
192
devices/Printers/ESC_POS/ESC_POS_Printer.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
//Reference: https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=72
|
||||
|
||||
#include "ESC_POS_Printer.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
|
||||
#else
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ESC_POS_Printer::ESC_POS_Printer()
|
||||
{
|
||||
m_hPrinter = NULL;
|
||||
m_usb = false;
|
||||
m_Serial = NULL;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
ESC_POS_Printer::~ESC_POS_Printer()
|
||||
{
|
||||
if (m_Serial != NULL)
|
||||
{
|
||||
close();
|
||||
delete m_Serial;
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool ESC_POS_Printer::openSerial(std::string ComNumber)
|
||||
{
|
||||
m_Serial->Open(ComNumber);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool ESC_POS_Printer::openUSB(std::wstring printerName)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
|
||||
bool result=true;
|
||||
if (!OpenPrinter((LPWSTR)printerName.c_str(), &m_hPrinter, NULL))
|
||||
result = false;
|
||||
m_usb = true;
|
||||
return result;
|
||||
#else
|
||||
std::string str( printerName.begin(), printerName.end() );
|
||||
return openUSB(str);
|
||||
#endif
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool ESC_POS_Printer::openUSB(std::string printerName)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
|
||||
bool result=true;
|
||||
if (!OpenPrinter((LPWSTR)printerName.c_str(), &m_hPrinter, NULL))
|
||||
result = false;
|
||||
m_usb = true;
|
||||
return result;
|
||||
#else
|
||||
m_hPrinter = fopen(printerName.c_str(), "w");
|
||||
if(m_hPrinter)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool ESC_POS_Printer::Start()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
|
||||
DWORD Level = 1;
|
||||
std::wstring docName = L"Print ticket";
|
||||
|
||||
DOC_INFO_1 pDocInfo;
|
||||
pDocInfo.pDocName = (LPWSTR)docName.c_str();
|
||||
pDocInfo.pOutputFile = NULL;
|
||||
pDocInfo.pDatatype = NULL;
|
||||
|
||||
bool result = true;
|
||||
StartDocPrinter(m_hPrinter, Level, (BYTE*)&pDocInfo);
|
||||
if (!StartPagePrinter(m_hPrinter))
|
||||
result = false;
|
||||
return result;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool ESC_POS_Printer::End()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
|
||||
bool result = true;
|
||||
if (!EndPagePrinter(m_hPrinter))
|
||||
result = false;
|
||||
if (!EndDocPrinter(m_hPrinter))
|
||||
result = false;
|
||||
return result;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool ESC_POS_Printer::close()
|
||||
{
|
||||
if (m_Serial != NULL)
|
||||
{
|
||||
m_Serial->Close();
|
||||
}
|
||||
if (m_hPrinter != NULL)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
|
||||
if (!EndPagePrinter(m_hPrinter))
|
||||
return false;
|
||||
if (!EndDocPrinter(m_hPrinter))
|
||||
return false;
|
||||
ClosePrinter(m_hPrinter);
|
||||
#else
|
||||
if(fclose(m_hPrinter)==0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
//width - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 8)
|
||||
//height - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//bitArray - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
bool ESC_POS_Printer::printImage(int width, int height, unsigned char* bitArray)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
|
||||
DWORD Written = 0;
|
||||
int arLen = (width * height) / 8;
|
||||
|
||||
char bCmdPrint[] = { 0x1d, 0x76, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
int w = width;
|
||||
int h = height;
|
||||
bCmdPrint[4] = (((w / 8) >> 0) & 0xFF); //xL <20> xL and xH specify the horizontal direction data count for one bit image (xL + xH x 256) in bytes
|
||||
bCmdPrint[5] = (((w / 8) >> 8) & 0xFF); //xH
|
||||
bCmdPrint[6] = ((h >> 0) & 0xFF); //yL <20> yL and yH specify the vertical direction data count for one bit image (yL + yH x 256) in dots.
|
||||
bCmdPrint[7] = ((h >> 8) & 0xFF); //yH
|
||||
WritePrinter(m_hPrinter, bCmdPrint, sizeof(bCmdPrint), &Written);
|
||||
WritePrinter(m_hPrinter, bitArray, arLen, &Written);
|
||||
|
||||
return arLen == Written;
|
||||
#else
|
||||
int Written = 0;
|
||||
int arLen = (width * height) / 8;
|
||||
|
||||
char bCmdPrint[] = { 0x1d, 0x76, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
int w = width;
|
||||
int h = height;
|
||||
bCmdPrint[4] = (((w / 8) >> 0) & 0xFF); //xL <20> xL and xH specify the horizontal direction data count for one bit image (xL + xH x 256) in bytes
|
||||
bCmdPrint[5] = (((w / 8) >> 8) & 0xFF); //xH
|
||||
bCmdPrint[6] = ((h >> 0) & 0xFF); //yL <20> yL and yH specify the vertical direction data count for one bit image (yL + yH x 256) in dots.
|
||||
bCmdPrint[7] = ((h >> 8) & 0xFF); //yH
|
||||
|
||||
Written = fwrite(bCmdPrint, sizeof(char), sizeof(bCmdPrint), m_hPrinter);
|
||||
Written = fwrite(bitArray, sizeof(char), arLen, m_hPrinter);
|
||||
|
||||
return arLen == Written;
|
||||
#endif
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool ESC_POS_Printer::Feed()
|
||||
{
|
||||
char bCmdFeed[] = { 27, 100, 5 };
|
||||
|
||||
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
|
||||
DWORD Written = 0;
|
||||
WritePrinter(m_hPrinter, bCmdFeed, sizeof(bCmdFeed), &Written);
|
||||
return Written == 3;
|
||||
#else
|
||||
int Written = 0;
|
||||
Written = fwrite(bCmdFeed, sizeof(char), sizeof(bCmdFeed), m_hPrinter);
|
||||
fflush(m_hPrinter);
|
||||
return Written == 3;
|
||||
#endif
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool ESC_POS_Printer::Cut()
|
||||
{
|
||||
char bCmdCut[] = { 0x1B,0x6D };
|
||||
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
|
||||
DWORD Written = 0;
|
||||
WritePrinter(m_hPrinter, bCmdCut, sizeof(bCmdCut), &Written);
|
||||
return Written == 2;
|
||||
#else
|
||||
int Written = 0;
|
||||
fwrite(bCmdCut, sizeof(char),sizeof(bCmdCut), m_hPrinter);
|
||||
fflush(m_hPrinter);
|
||||
return Written == 2;
|
||||
#endif
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
41
devices/Printers/ESC_POS/ESC_POS_Printer.h
Normal file
41
devices/Printers/ESC_POS/ESC_POS_Printer.h
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
#ifndef ESC_POS_PRINTER_H
|
||||
#define ESC_POS_PRINTER_H
|
||||
|
||||
#include <string>
|
||||
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
|
||||
#include <windows.h>
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
#include "ComPort.h"
|
||||
|
||||
class ESC_POS_Printer {
|
||||
public:
|
||||
|
||||
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
|
||||
HANDLE m_hPrinter;
|
||||
#else
|
||||
FILE* m_hPrinter;
|
||||
#endif
|
||||
ComPort* m_Serial;
|
||||
|
||||
ESC_POS_Printer();
|
||||
~ESC_POS_Printer();
|
||||
|
||||
bool openSerial(std::string ComNumber);
|
||||
bool openUSB(std::wstring printerName);
|
||||
bool openUSB(std::string printerName);
|
||||
bool close();
|
||||
|
||||
bool Start();
|
||||
bool printImage(int width, int height, unsigned char* bitArray);
|
||||
bool Feed(); //Прокрутить бумагу
|
||||
bool Cut(); //Отрезать бумагу
|
||||
bool End();
|
||||
private:
|
||||
bool m_usb;
|
||||
};
|
||||
|
||||
#endif
|
||||
536
devices/Printers/ESC_POS/Документация/ESC_POS_Printer.cpp
Normal file
536
devices/Printers/ESC_POS/Документация/ESC_POS_Printer.cpp
Normal file
@ -0,0 +1,536 @@
|
||||
/*------------------------------------------------------------------------
|
||||
An Arduino library for the USB Thermal Printer using Epson ESC POS commands
|
||||
|
||||
These printers use USB to communicate.
|
||||
|
||||
This library is based on the Adafruit Thermal Printer Library.
|
||||
|
||||
Adafruit invests time and resources providing this open source code.
|
||||
Please support USB and open-source hardware by purchasing products
|
||||
from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries, with
|
||||
contributions from the open source community. Originally based on
|
||||
Thermal library from bildr.org
|
||||
MIT license, all text above must be included in any redistribution.
|
||||
|
||||
Reference: https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=72
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
#include "ESC_POS_Printer.h"
|
||||
|
||||
// ASCII codes used by some of the printer config commands:
|
||||
#define ASCII_TAB '\t' // Horizontal tab
|
||||
#define ASCII_LF '\n' // Line feed
|
||||
#define ASCII_FF '\f' // Form feed
|
||||
#define ASCII_CR '\r' // Carriage return
|
||||
#define ASCII_EOT 4 // End of Transmission
|
||||
#define ASCII_DLE 16 // Data Link Escape
|
||||
#define ASCII_DC2 18 // Device control 2
|
||||
#define ASCII_ESC 27 // Escape
|
||||
#define ASCII_FS 28 // Field separator
|
||||
#define ASCII_GS 29 // Group separator
|
||||
|
||||
// Constructor
|
||||
ESC_POS_Printer::ESC_POS_Printer(Stream *s) :
|
||||
stream(s) {
|
||||
}
|
||||
|
||||
// The next four helper methods are used when issuing configuration
|
||||
// commands, printing bitmaps or barcodes, etc. Not when printing text.
|
||||
|
||||
void ESC_POS_Printer::writeBytes(uint8_t a) {
|
||||
stream->write(a);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::writeBytes(uint8_t a, uint8_t b) {
|
||||
uint8_t cmd[2] = {a, b};
|
||||
stream->write(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::writeBytes(uint8_t a, uint8_t b, uint8_t c) {
|
||||
uint8_t cmd[3] = {a, b, c};
|
||||
stream->write(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::writeBytes(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
|
||||
uint8_t cmd[4] = {a, b, c, d};
|
||||
stream->write(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
// The underlying method for all high-level printing (e.g. println()).
|
||||
// The inherited Print class handles the rest!
|
||||
size_t ESC_POS_Printer::write(uint8_t c) {
|
||||
|
||||
if(c != 0x13) { // Strip carriage returns
|
||||
stream->write(c);
|
||||
if((c == '\n') || (column == maxColumn)) { // If newline or wrap
|
||||
column = 0;
|
||||
c = '\n'; // Treat wrap as newline on next pass
|
||||
} else {
|
||||
column++;
|
||||
}
|
||||
prevByte = c;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::begin() {
|
||||
|
||||
// The printer can't start receiving data immediately upon power up --
|
||||
// it needs a moment to cold boot and initialize. Allow at least 1/2
|
||||
// sec of uptime before printer can receive data.
|
||||
|
||||
wake();
|
||||
reset();
|
||||
}
|
||||
|
||||
// Reset printer to default state.
|
||||
void ESC_POS_Printer::reset() {
|
||||
writeBytes(ASCII_ESC, '@'); // Init command
|
||||
prevByte = '\n'; // Treat as if prior line is blank
|
||||
column = 0;
|
||||
maxColumn = 32;
|
||||
charHeight = 24;
|
||||
lineSpacing = 6;
|
||||
barcodeHeight = 50;
|
||||
}
|
||||
|
||||
// Reset text formatting parameters.
|
||||
void ESC_POS_Printer::setDefault(){
|
||||
online();
|
||||
justify('L');
|
||||
inverseOff();
|
||||
doubleHeightOff();
|
||||
setLineHeight(30);
|
||||
boldOff();
|
||||
underlineOff();
|
||||
setBarcodeHeight(50);
|
||||
setSize('s');
|
||||
setCharset();
|
||||
setCodePage();
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::test(){
|
||||
println(F("Hello World!"));
|
||||
feed(2);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::testPage() {
|
||||
char commandTest[] = {ASCII_GS, '(', 'A', 2, 0, 0, 3};
|
||||
stream->write(commandTest, sizeof(commandTest));
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::setBarcodeHeight(uint8_t val) { // Default is 50
|
||||
if(val < 1) val = 1;
|
||||
barcodeHeight = val;
|
||||
// This does not work on my printer. It prints a '2' = 0x32 = 50
|
||||
//writeBytes(ASCII_GS, 'h', val);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::printBarcode(const char *text, uint8_t type) {
|
||||
feed(1); // Recent firmware can't print barcode w/o feed first???
|
||||
writeBytes(ASCII_GS, 'H', 2); // Print label below barcode
|
||||
writeBytes(ASCII_GS, 'w', 3); // Barcode width 3 (0.375/1.0mm thin/thick)
|
||||
writeBytes(ASCII_GS, 'k', type); // Barcode type (listed in .h file)
|
||||
// Write text including the terminating '\0'
|
||||
stream->write(text, strlen(text)+1);
|
||||
prevByte = '\n';
|
||||
}
|
||||
|
||||
// === Character commands ===
|
||||
|
||||
#define INVERSE_MASK (1 << 1) // Not in 2.6.8 firmware (see inverseOn())
|
||||
//#define UPDOWN_MASK (1 << 2)
|
||||
//#define BOLD_MASK (1 << 3)
|
||||
#define DOUBLE_HEIGHT_MASK (1 << 4)
|
||||
#define DOUBLE_WIDTH_MASK (1 << 5)
|
||||
//#define STRIKE_MASK (1 << 6)
|
||||
#define UNDERLINE_MASK (1 << 7)
|
||||
|
||||
void ESC_POS_Printer::setPrintMode(uint8_t mask) {
|
||||
printMode |= mask;
|
||||
writePrintMode();
|
||||
charHeight = (printMode & DOUBLE_HEIGHT_MASK) ? 48 : 24;
|
||||
maxColumn = (printMode & DOUBLE_WIDTH_MASK ) ? 16 : 32;
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::unsetPrintMode(uint8_t mask) {
|
||||
printMode &= ~mask;
|
||||
writePrintMode();
|
||||
charHeight = (printMode & DOUBLE_HEIGHT_MASK) ? 48 : 24;
|
||||
maxColumn = (printMode & DOUBLE_WIDTH_MASK ) ? 16 : 32;
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::writePrintMode() {
|
||||
writeBytes(ASCII_ESC, '!', printMode);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::normal() {
|
||||
printMode = 0;
|
||||
writePrintMode();
|
||||
upsideDownOff();
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::inverseOn(){
|
||||
writeBytes(ASCII_GS, 'B', 1);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::inverseOff(){
|
||||
writeBytes(ASCII_GS, 'B', 0);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::upsideDownOn(){
|
||||
writeBytes(ASCII_ESC, '{', 1);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::upsideDownOff(){
|
||||
writeBytes(ASCII_ESC, '{', 0);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::doubleHeightOn(){
|
||||
setPrintMode(DOUBLE_HEIGHT_MASK);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::doubleHeightOff(){
|
||||
unsetPrintMode(DOUBLE_HEIGHT_MASK);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::doubleWidthOn(){
|
||||
setPrintMode(DOUBLE_WIDTH_MASK);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::doubleWidthOff(){
|
||||
unsetPrintMode(DOUBLE_WIDTH_MASK);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::strikeOn(){
|
||||
writeBytes(ASCII_ESC, 'G', 1);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::strikeOff(){
|
||||
writeBytes(ASCII_ESC, 'G', 0);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::boldOn(){
|
||||
writeBytes(ASCII_ESC, 'E', 1);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::boldOff(){
|
||||
writeBytes(ASCII_ESC, 'E', 0);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::justify(char value){
|
||||
uint8_t pos = 0;
|
||||
|
||||
switch(toupper(value)) {
|
||||
case 'L': pos = 0; break;
|
||||
case 'C': pos = 1; break;
|
||||
case 'R': pos = 2; break;
|
||||
}
|
||||
|
||||
writeBytes(ASCII_ESC, 'a', pos);
|
||||
}
|
||||
|
||||
// Feeds by the specified number of lines
|
||||
void ESC_POS_Printer::feed(uint8_t x) {
|
||||
writeBytes(ASCII_ESC, 'd', x);
|
||||
prevByte = '\n';
|
||||
column = 0;
|
||||
}
|
||||
|
||||
// Feeds by the specified number of individual pixel rows
|
||||
void ESC_POS_Printer::feedRows(uint8_t rows) {
|
||||
writeBytes(ASCII_ESC, 'J', rows);
|
||||
prevByte = '\n';
|
||||
column = 0;
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::flush() {
|
||||
writeBytes(ASCII_FF);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::setSize(char value){
|
||||
uint8_t size;
|
||||
|
||||
switch(toupper(value)) {
|
||||
default: // Small: standard width and height
|
||||
size = 0x00;
|
||||
charHeight = 24;
|
||||
maxColumn = 32;
|
||||
break;
|
||||
case 'M': // Medium: double height
|
||||
size = 0x01;
|
||||
charHeight = 48;
|
||||
maxColumn = 32;
|
||||
break;
|
||||
case 'L': // Large: double width and height
|
||||
size = 0x11;
|
||||
charHeight = 48;
|
||||
maxColumn = 64;
|
||||
break;
|
||||
}
|
||||
|
||||
writeBytes(ASCII_GS, '!', size);
|
||||
prevByte = '\n'; // Setting the size adds a linefeed
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::setSize(uint8_t height, uint8_t width) {
|
||||
uint8_t size = ((width & 0x7) << 3) | (height & 0x7);
|
||||
|
||||
writeBytes(ASCII_GS, '!', size);
|
||||
prevByte = '\n'; // Setting the size adds a linefeed
|
||||
}
|
||||
|
||||
// Underlines of different weights can be produced:
|
||||
// 0 - no underline
|
||||
// 1 - normal underline
|
||||
// 2 - thick underline
|
||||
void ESC_POS_Printer::underlineOn(uint8_t weight) {
|
||||
if(weight > 2) weight = 2;
|
||||
writeBytes(ASCII_ESC, '-', weight);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::underlineOff() {
|
||||
writeBytes(ASCII_ESC, '-', 0);
|
||||
}
|
||||
|
||||
// ASCII ESC * m nL nH d1...dk
|
||||
// Hex 1B 2A m nL nH d1...dk
|
||||
// Dec 27 42 m nL nH d1...dk
|
||||
// m = 0 single density vert, single horizontal
|
||||
// m = 1 single density vert, double horiz
|
||||
// m = 32 double density vert, single horizontal
|
||||
// m = 33 double density vert, double horiz
|
||||
void ESC_POS_Printer::printBitmap(
|
||||
int w, int h, const uint8_t *bitmap, int density) {
|
||||
uint8_t band_height;
|
||||
uint8_t bitmap_command[] = { 0x1b, '*', 0, 0, 0 };
|
||||
size_t w_bytes = w;
|
||||
|
||||
switch (density) {
|
||||
default:
|
||||
density = 1;
|
||||
/* fall through */
|
||||
case 1:
|
||||
bitmap_command[2] = 0; // m = single density
|
||||
band_height = 8;
|
||||
break;
|
||||
case 2:
|
||||
bitmap_command[2] = 33; // m = double density
|
||||
band_height = 24;
|
||||
w_bytes *= 3;
|
||||
break;
|
||||
}
|
||||
bitmap_command[3] = w & 0xFF; // nL = width LS byte
|
||||
bitmap_command[4] = (w >> 8) & 0xFF;// nH = width MS byte
|
||||
|
||||
// Line spacing = 16 dots
|
||||
stream->write("\x1b\x33\x10\x1bU\x01"); // Unidirectional print mode on
|
||||
for (int row = 0; row < h; row += band_height) {
|
||||
stream->write(bitmap_command, sizeof(bitmap_command));
|
||||
stream->write(bitmap, w_bytes);
|
||||
stream->write('\n');
|
||||
bitmap += w_bytes;
|
||||
}
|
||||
stream->write("\x1b\x32\x1bU"); // Default line spacing
|
||||
stream->write((uint8_t)0); // Unidirectional print mode off
|
||||
prevByte = '\n';
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::printBitmap_P(
|
||||
int w, int h, const uint8_t *bitmap, int density) {
|
||||
uint8_t band_height;
|
||||
uint8_t bitmap_command[] = { 0x1b, '*', 0, 0, 0 };
|
||||
size_t w_bytes = w;
|
||||
uint8_t buf[64];
|
||||
PGM_P p = reinterpret_cast<PGM_P>(bitmap);
|
||||
|
||||
switch (density) {
|
||||
default:
|
||||
density = 1;
|
||||
/* fall through */
|
||||
case 1:
|
||||
bitmap_command[2] = 0; // m = single density
|
||||
band_height = 8;
|
||||
break;
|
||||
case 2:
|
||||
bitmap_command[2] = 33; // m = double density
|
||||
band_height = 24;
|
||||
w_bytes *= 3;
|
||||
break;
|
||||
}
|
||||
bitmap_command[3] = w & 0xFF; // nL = width LS byte
|
||||
bitmap_command[4] = (w >> 8) & 0xFF;// nH = width MS byte
|
||||
|
||||
// Line spacing = 16 dots
|
||||
stream->write("\x1b\x33\x10\x1bU\x01"); // Unidirectional print mode on
|
||||
for (int row = 0; row < h; row += band_height) {
|
||||
memcpy(buf, bitmap_command, sizeof(bitmap_command));
|
||||
size_t len = sizeof(bitmap_command);
|
||||
size_t outlen;
|
||||
for (size_t col = 0; col < w_bytes; col += outlen) {
|
||||
outlen = min(sizeof(buf)-len, w_bytes - col);
|
||||
memcpy_P(buf+len, p, outlen);
|
||||
len += outlen;
|
||||
p += outlen;
|
||||
stream->write(buf, len);
|
||||
len = 0;
|
||||
}
|
||||
stream->write('\n');
|
||||
}
|
||||
// The count correctly includes the trailing '\0'!
|
||||
stream->write("\x1b\x32\x1bU", 5); // Default line spacing,
|
||||
// Unidirectional print mode off
|
||||
prevByte = '\n';
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::printBitmap(
|
||||
int w, int h, const uint8_t *bitmap, bool fromProgMem) {
|
||||
int rowBytes, rowBytesClipped, rowStart, chunkHeight, chunkHeightLimit,
|
||||
x, y, i;
|
||||
|
||||
rowBytes = (w + 7) / 8; // Round up to next byte boundary
|
||||
rowBytesClipped = (rowBytes >= 48) ? 48 : rowBytes; // 384 pixels max width
|
||||
|
||||
chunkHeightLimit = 255; // Buffer doesn't matter, handshake!
|
||||
|
||||
for(i=rowStart=0; rowStart < h; rowStart += chunkHeightLimit) {
|
||||
// Issue up to chunkHeightLimit rows at a time:
|
||||
chunkHeight = h - rowStart;
|
||||
if(chunkHeight > chunkHeightLimit) chunkHeight = chunkHeightLimit;
|
||||
|
||||
writeBytes(ASCII_DC2, '*', chunkHeight, rowBytesClipped);
|
||||
|
||||
for(y=0; y < chunkHeight; y++) {
|
||||
for(x=0; x < rowBytesClipped; x++, i++) {
|
||||
stream->write(fromProgMem ? pgm_read_byte(bitmap + i) : *(bitmap+i));
|
||||
}
|
||||
i += rowBytes - rowBytesClipped;
|
||||
}
|
||||
}
|
||||
prevByte = '\n';
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::printBitmap(int w, int h, Stream *fromStream) {
|
||||
int rowBytes, rowBytesClipped, rowStart, chunkHeight, chunkHeightLimit,
|
||||
x, y, i, c;
|
||||
|
||||
rowBytes = (w + 7) / 8; // Round up to next byte boundary
|
||||
rowBytesClipped = (rowBytes >= 48) ? 48 : rowBytes; // 384 pixels max width
|
||||
|
||||
// Est. max rows to write at once, assuming 256 byte printer buffer.
|
||||
chunkHeightLimit = 255; // Buffer doesn't matter, handshake!
|
||||
|
||||
for(rowStart=0; rowStart < h; rowStart += chunkHeightLimit) {
|
||||
// Issue up to chunkHeightLimit rows at a time:
|
||||
chunkHeight = h - rowStart;
|
||||
if(chunkHeight > chunkHeightLimit) chunkHeight = chunkHeightLimit;
|
||||
|
||||
writeBytes(ASCII_DC2, '*', chunkHeight, rowBytesClipped);
|
||||
|
||||
for(y=0; y < chunkHeight; y++) {
|
||||
for(x=0; x < rowBytesClipped; x++) {
|
||||
while((c = fromStream->read()) < 0);
|
||||
stream->write((uint8_t)c);
|
||||
}
|
||||
for(i = rowBytes - rowBytesClipped; i>0; i--) {
|
||||
while((c = fromStream->read()) < 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
prevByte = '\n';
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::printBitmap(Stream *fromStream) {
|
||||
uint8_t tmp;
|
||||
uint16_t width, height;
|
||||
|
||||
tmp = fromStream->read();
|
||||
width = (fromStream->read() << 8) + tmp;
|
||||
|
||||
tmp = fromStream->read();
|
||||
height = (fromStream->read() << 8) + tmp;
|
||||
|
||||
printBitmap(width, height, fromStream);
|
||||
}
|
||||
|
||||
// Take the printer offline. Print commands sent after this will be
|
||||
// ignored until 'online' is called.
|
||||
void ESC_POS_Printer::offline(){
|
||||
writeBytes(ASCII_ESC, '=', 0);
|
||||
}
|
||||
|
||||
// Take the printer back online. Subsequent print commands will be obeyed.
|
||||
void ESC_POS_Printer::online(){
|
||||
writeBytes(ASCII_ESC, '=', 1);
|
||||
}
|
||||
|
||||
// Put the printer into a low-energy state immediately.
|
||||
void ESC_POS_Printer::sleep() {
|
||||
sleepAfter(1); // Can't be 0, that means 'don't sleep'
|
||||
}
|
||||
|
||||
// Put the printer into a low-energy state after the given number
|
||||
// of seconds.
|
||||
void ESC_POS_Printer::sleepAfter(uint16_t seconds) {
|
||||
writeBytes(ASCII_ESC, '8', seconds, seconds >> 8);
|
||||
}
|
||||
|
||||
// Wake the printer from a low-energy state.
|
||||
void ESC_POS_Printer::wake() {
|
||||
}
|
||||
|
||||
// Check the status of the paper using the printer's self reporting
|
||||
// ability. Returns true for paper, false for no paper.
|
||||
// Might not work on all printers!
|
||||
bool ESC_POS_Printer::hasPaper() {
|
||||
// writeBytes(ASCII_DLE, ASCII_EOT, 4);
|
||||
writeBytes(ASCII_GS, 'r', 1);
|
||||
// writeBytes(ASCII_ESC, 'v');
|
||||
|
||||
int status = 0;
|
||||
for(uint8_t i=0; i<10; i++) {
|
||||
if(stream->available()) {
|
||||
status = stream->read();
|
||||
break;
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
|
||||
return !(status & 0b00001100);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::setLineHeight(int val) {
|
||||
if(val < 24) val = 24;
|
||||
lineSpacing = val - 24;
|
||||
|
||||
// The printer doesn't take into account the current text height
|
||||
// when setting line height, making this more akin to inter-line
|
||||
// spacing. Default line spacing is 30 (char height of 24, line
|
||||
// spacing of 6).
|
||||
writeBytes(ASCII_ESC, '3', val);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::setMaxChunkHeight(int val) {
|
||||
}
|
||||
|
||||
// Alters some chars in ASCII 0x23-0x7E range; see datasheet
|
||||
void ESC_POS_Printer::setCharset(uint8_t val) {
|
||||
writeBytes(ASCII_ESC, 'R', val);
|
||||
}
|
||||
|
||||
// Selects alt symbols for 'upper' ASCII values 0x80-0xFF
|
||||
void ESC_POS_Printer::setCodePage(uint8_t val) {
|
||||
writeBytes(ASCII_ESC, 't', val);
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::tab() {
|
||||
writeBytes(ASCII_TAB);
|
||||
column = (column + 4) & 0b11111100;
|
||||
}
|
||||
|
||||
void ESC_POS_Printer::setCharSpacing(int spacing) {
|
||||
writeBytes(ASCII_ESC, ' ', spacing);
|
||||
}
|
||||
198
devices/Printers/ESC_POS/Документация/ESC_POS_Printer.h
Normal file
198
devices/Printers/ESC_POS/Документация/ESC_POS_Printer.h
Normal file
@ -0,0 +1,198 @@
|
||||
/*------------------------------------------------------------------------
|
||||
An Arduino library for the USB Thermal Printer using Epson ESC POS commands
|
||||
|
||||
These printers use USB to communicate.
|
||||
|
||||
This library is based on the Adafruit Thermal Printer Library.
|
||||
|
||||
Adafruit invests time and resources providing this open source code.
|
||||
Please support USB and open-source hardware by purchasing products
|
||||
from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries, with
|
||||
contributions from the open source community. Originally based on
|
||||
Thermal library from bildr.org
|
||||
MIT license, all text above must be included in any redistribution.
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef ESC_POS_PRINTER_H
|
||||
#define ESC_POS_PRINTER_H
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
// Barcode types and charsets
|
||||
#define UPC_A 65
|
||||
#define UPC_E 66
|
||||
#define EAN13 67
|
||||
#define EAN8 68
|
||||
#define CODE39 69
|
||||
#define ITF 70
|
||||
#define CODABAR 71
|
||||
#define CODE93 72
|
||||
#define CODE128 73
|
||||
#define GS1_128 74
|
||||
#define GS1_DATABAR_OMNI 75
|
||||
#define GS1_DATABAR_TRUNC 76
|
||||
#define GS1_DATABAR_LIMTD 77
|
||||
#define GS1_DATABAR_EXPAN 78
|
||||
|
||||
#define CHARSET_USA 0
|
||||
#define CHARSET_FRANCE 1
|
||||
#define CHARSET_GERMANY 2
|
||||
#define CHARSET_UK 3
|
||||
#define CHARSET_DENMARK1 4
|
||||
#define CHARSET_SWEDEN 5
|
||||
#define CHARSET_ITALY 6
|
||||
#define CHARSET_SPAIN1 7
|
||||
#define CHARSET_JAPAN 8
|
||||
#define CHARSET_NORWAY 9
|
||||
#define CHARSET_DENMARK2 10
|
||||
#define CHARSET_SPAIN2 11
|
||||
#define CHARSET_LATINAMERICA 12
|
||||
#define CHARSET_KOREA 13
|
||||
#define CHARSET_SLOVENIA 14
|
||||
#define CHARSET_CROATIA 14
|
||||
#define CHARSET_CHINA 15
|
||||
#define CHARSET_VIETNAM 16
|
||||
#define CHARSET_ARABIA 17
|
||||
#define CHARSET_INDIA_DEVANAGARI 66
|
||||
#define CHARSET_INDIA_BENGALI 67
|
||||
#define CHARSET_INDIA_TAMIL 68
|
||||
#define CHARSET_INDIA_TELUGU 69
|
||||
#define CHARSET_INDIA_ASSAMESE 70
|
||||
#define CHARSET_INDIA_ORIYA 71
|
||||
#define CHARSET_INDIA_KANNANDA 72
|
||||
#define CHARSET_INDIA_MALAYALAM 73
|
||||
#define CHARSET_INDIA_GUJARATI 74
|
||||
#define CHARSET_INDIA_PUNJABI 75
|
||||
#define CHARSET_INDIA_MARATHI 82
|
||||
|
||||
#define CODEPAGE_CP437 0 // USA, Standard Europe
|
||||
#define CODEPAGE_KATAKANA 1
|
||||
#define CODEPAGE_CP850 2 // Multilingual
|
||||
#define CODEPAGE_CP860 3 // Portuguese
|
||||
#define CODEPAGE_CP863 4 // Canadian-French
|
||||
#define CODEPAGE_CP865 5 // Nordic
|
||||
#define CODEPAGE_WCP1251 6 // Cyrillic
|
||||
#define CODEPAGE_CP866 7 // Cyrillic #2
|
||||
#define CODEPAGE_MIK 8 // Cyrillic/Bulgarian
|
||||
#define CODEPAGE_CP755 9 // East Europe, Latvian 2
|
||||
#define CODEPAGE_IRAN 10
|
||||
#define CODEPAGE_CP862 15 // Hebrew
|
||||
#define CODEPAGE_WCP1252 16 // Latin 1
|
||||
#define CODEPAGE_WCP1253 17 // Greek
|
||||
#define CODEPAGE_CP852 18 // Latin 2
|
||||
#define CODEPAGE_CP858 19 // Multilingual Latin 1 + Euro
|
||||
#define CODEPAGE_IRAN2 20
|
||||
#define CODEPAGE_LATVIAN 21
|
||||
#define CODEPAGE_CP864 22 // Arabic
|
||||
#define CODEPAGE_ISO_8859_1 23 // West Europe
|
||||
#define CODEPAGE_CP737 24 // Greek
|
||||
#define CODEPAGE_WCP1257 25 // Baltic
|
||||
#define CODEPAGE_THAI 26
|
||||
#define CODEPAGE_CP720 27 // Arabic
|
||||
#define CODEPAGE_CP855 28
|
||||
#define CODEPAGE_CP857 29 // Turkish
|
||||
#define CODEPAGE_WCP1250 30 // Central Europe
|
||||
#define CODEPAGE_CP775 31
|
||||
#define CODEPAGE_WCP1254 32 // Turkish
|
||||
#define CODEPAGE_WCP1255 33 // Hebrew
|
||||
#define CODEPAGE_WCP1256 34 // Arabic
|
||||
#define CODEPAGE_WCP1258 35 // Vietnam
|
||||
#define CODEPAGE_ISO_8859_2 36 // Latin 2
|
||||
#define CODEPAGE_ISO_8859_3 37 // Latin 3
|
||||
#define CODEPAGE_ISO_8859_4 38 // Baltic
|
||||
#define CODEPAGE_ISO_8859_5 39 // Cyrillic
|
||||
#define CODEPAGE_ISO_8859_6 40 // Arabic
|
||||
#define CODEPAGE_ISO_8859_7 41 // Greek
|
||||
#define CODEPAGE_ISO_8859_8 42 // Hebrew
|
||||
#define CODEPAGE_ISO_8859_9 43 // Turkish
|
||||
#define CODEPAGE_ISO_8859_15 44 // Latin 3
|
||||
#define CODEPAGE_THAI2 45
|
||||
#define CODEPAGE_CP856 46
|
||||
#define CODEPAGE_CP874 47
|
||||
|
||||
class ESC_POS_Printer : public Print {
|
||||
|
||||
public:
|
||||
|
||||
// IMPORTANT: constructor syntax has changed from prior versions
|
||||
// of this library. Please see notes in the example code!
|
||||
ESC_POS_Printer(Stream *s=&Serial);
|
||||
|
||||
size_t
|
||||
write(uint8_t c);
|
||||
void
|
||||
begin(),
|
||||
boldOff(),
|
||||
boldOn(),
|
||||
doubleHeightOff(),
|
||||
doubleHeightOn(),
|
||||
doubleWidthOff(),
|
||||
doubleWidthOn(),
|
||||
feed(uint8_t x=1),
|
||||
feedRows(uint8_t),
|
||||
flush(),
|
||||
inverseOff(),
|
||||
inverseOn(),
|
||||
justify(char value),
|
||||
offline(),
|
||||
online(),
|
||||
printBarcode(const char *text, uint8_t type),
|
||||
printBitmap(int w, int h, const uint8_t *bitmap, int density=1),
|
||||
printBitmap_P(int w, int h, const uint8_t *bitmap, int density=1),
|
||||
printBitmap(int w, int h, const uint8_t *bitmap, bool fromProgMem=true),
|
||||
printBitmap(int w, int h, Stream *fromStream),
|
||||
printBitmap(Stream *fromStream),
|
||||
normal(),
|
||||
reset(),
|
||||
setBarcodeHeight(uint8_t val=50),
|
||||
setCharSpacing(int spacing=0),
|
||||
setCharset(uint8_t val=0),
|
||||
setCodePage(uint8_t val=0),
|
||||
setDefault(),
|
||||
setLineHeight(int val=30),
|
||||
setMaxChunkHeight(int val=256),
|
||||
setSize(char value),
|
||||
setSize(uint8_t height, uint8_t width),
|
||||
setTimes(unsigned long, unsigned long),
|
||||
sleep(),
|
||||
sleepAfter(uint16_t seconds),
|
||||
strikeOff(),
|
||||
strikeOn(),
|
||||
tab(),
|
||||
test(),
|
||||
testPage(),
|
||||
underlineOff(),
|
||||
underlineOn(uint8_t weight=1),
|
||||
upsideDownOff(),
|
||||
upsideDownOn(),
|
||||
wake();
|
||||
bool
|
||||
hasPaper();
|
||||
|
||||
private:
|
||||
|
||||
Stream
|
||||
*stream;
|
||||
uint8_t
|
||||
printMode,
|
||||
prevByte, // Last character issued to printer
|
||||
column, // Last horizontal column printed
|
||||
maxColumn, // Page width (output 'wraps' at this point)
|
||||
charHeight, // Height of characters, in 'dots'
|
||||
lineSpacing, // Inter-line spacing (not line height), in dots
|
||||
barcodeHeight, // Barcode height in dots, not including text
|
||||
maxChunkHeight;
|
||||
void
|
||||
writeBytes(uint8_t a),
|
||||
writeBytes(uint8_t a, uint8_t b),
|
||||
writeBytes(uint8_t a, uint8_t b, uint8_t c),
|
||||
writeBytes(uint8_t a, uint8_t b, uint8_t c, uint8_t d),
|
||||
setPrintMode(uint8_t mask),
|
||||
unsetPrintMode(uint8_t mask),
|
||||
writePrintMode();
|
||||
|
||||
};
|
||||
|
||||
#endif // ESC_POS_PRINTER_H
|
||||
16
devices/Printers/ESC_POS/Документация/constants.h
Normal file
16
devices/Printers/ESC_POS/Документация/constants.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef ESCPOSPRINTER_CONSTANTS_H
|
||||
#define ESCPOSPRINTER_CONSTANTS_H
|
||||
|
||||
static const char *ESCPOS_CMD_INIT = "\x1b\x40";
|
||||
static const char *ESCPOS_CMD_PRINT_RASTER_BIT_IMAGE = "\x1d\x76\x30\x00";
|
||||
static const char *ESCPOS_CMD_CUT = "\x1d\x56\x42";
|
||||
static const char *ESCPOS_CMD_FEED = "\x1b\x64";
|
||||
|
||||
// The maximum width of image the printer can accept
|
||||
static const int ESCPOS_MAX_DOT_WIDTH = 576;
|
||||
|
||||
// When printing, if the image is too long, the printer
|
||||
// will cut the images into chunks of (w x ESCPOS_CHUNK_DOT_HEIGHT)
|
||||
static const int ESCPOS_CHUNK_DOT_HEIGHT = 512;
|
||||
|
||||
#endif
|
||||
63
devices/Printers/ESC_POS/Документация/epsonPrinter.h
Normal file
63
devices/Printers/ESC_POS/Документация/epsonPrinter.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* epsonPrinter.h
|
||||
* epson_print
|
||||
*
|
||||
* Created by base on 08/06/11.
|
||||
* Copyright 2011 __MyCompanyName__. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace epsonConstants {
|
||||
|
||||
const char CTL_LF = '\x0a'; // Print and line feed
|
||||
const char CTL_FF = '\x0c'; // Form feed
|
||||
const char CTL_CR = '\x0d'; // Carriage return
|
||||
const char CTL_HT = '\x09'; // Horizontal tab
|
||||
const char CTL_VT = '\x0b'; // Vertical tab
|
||||
// Printer hardware
|
||||
const char HW_INIT[2] = {'\x1b', '\x40'}; // Clear data in buffer and reset modes
|
||||
//const char HW_SELECT = '\x1b\x3d\x01'; // Printer select
|
||||
//const char HW_RESET = '\x1b\x3f\x0a\x00'; // Reset printer hardware
|
||||
// Cash Drawer
|
||||
const char CD_KICK_2[3] = {'\x1b', '\x70', '\x00'}; // Sends a pulse to pin 2 []
|
||||
const char CD_KICK_5[3] = {'\x1b', '\x70', '\x01'}; // Sends a pulse to pin 5 []
|
||||
// Paper
|
||||
const char PAPER_FULL_CUT[3] = {'\x1d', '\x56', '\x00'}; // Full cut paper
|
||||
const char PAPER_PART_CUT[3] = {'\x1d', '\x56', '\x01'}; // Partial cut paper
|
||||
// Text format
|
||||
const char TXT_NORMAL[3] = {'\x1b', '\x21', '\x00'}; // Normal text
|
||||
const char TXT_2HEIGHT[3] = {'\x1b', '\x21', '\x10'}; // Double height text
|
||||
const char TXT_2WIDTH[3] = {'\x1b', '\x21', '\x20'}; // Double width text
|
||||
const char TXT_UNDERL_OFF[3] = {'\x1b', '\x2d', '\x00'}; // Underline font OFF
|
||||
const char TXT_UNDERL_ON[3] = {'\x1b', '\x2d', '\x01'}; // Underline font 1-dot ON
|
||||
const char TXT_UNDERL2_ON[3] = {'\x1b', '\x2d', '\x02'}; // Underline font 2-dot ON
|
||||
const char TXT_BOLD_OFF[3] = {'\x1b', '\x45', '\x00'}; // Bold font OFF
|
||||
const char TXT_BOLD_ON[3] = { '\x1b', '\x45', '\x01'}; // Bold font ON
|
||||
const char TXT_FONT_A[3] = { '\x1b', '\x4d', '\x00'}; // Font type A
|
||||
const char TXT_FONT_B[3] = { '\x1b', '\x4d', '\x01'}; // Font type B
|
||||
const char TXT_ALIGN_LT[3] = { '\x1b', '\x61', '\x00'}; // Left justification
|
||||
const char TXT_ALIGN_CT[3] = { '\x1b', '\x61', '\x01'}; // Centering
|
||||
const char TXT_ALIGN_RT[3] = { '\x1b', '\x61', '\x02'}; // Right justification
|
||||
// Barcode format
|
||||
const char BARCODE_TXT_OFF[3] = { '\x1d', '\x48', '\x00'}; // HRI barcode chars OFF
|
||||
const char BARCODE_TXT_ABV[3] = { '\x1d', '\x48', '\x01'}; // HRI barcode chars above
|
||||
const char BARCODE_TXT_BLW[3] = { '\x1d', '\x48', '\x02'}; // HRI barcode chars below
|
||||
const char BARCODE_TXT_BTH[3] = { '\x1d', '\x48', '\x03'}; // HRI barcode chars both above and below
|
||||
const char BARCODE_FONT_A[3] = { '\x1d', '\x66', '\x00'}; // Font type A for HRI barcode chars
|
||||
const char BARCODE_FONT_B[3] = { '\x1d', '\x66', '\x01'}; // Font type B for HRI barcode chars
|
||||
const char BARCODE_HEIGHT[3] = { '\x1d', '\x68', '\x64'}; // Barcode Height [1-255]
|
||||
const char BARCODE_WIDTH[3] = { '\x1d', '\x77', '\x03'}; // Barcode Width [2-6]
|
||||
const char BARCODE_UPC_A[3] = { '\x1d', '\x6b', '\x00'}; // Barcode type UPC-A
|
||||
const char BARCODE_UPC_E[3] = { '\x1d', '\x6b', '\x01'}; // Barcode type UPC-E
|
||||
const char BARCODE_EAN13[3] = { '\x1d', '\x6b', '\x02'}; // Barcode type EAN13
|
||||
const char BARCODE_EAN8[3] = { '\x1d', '\x6b', '\x03'}; // Barcode type EAN8
|
||||
const char BARCODE_CODE39[3] = { '\x1d', '\x6b', '\x04'}; // Barcode type CODE39
|
||||
const char BARCODE_ITF[3] = { '\x1d', '\x6b', '\x05'}; // Barcode type ITF
|
||||
const char BARCODE_NW7[3] = { '\x1d', '\x6b', '\x06'}; // Barcode type NW7
|
||||
// Image format
|
||||
const char S_RASTER_N[4] = { '\x1d', '\x76', '\x30', '\x00'}; // Set raster image normal size
|
||||
const char S_RASTER_2W[4] = { '\x1d', '\x76', '\x30', '\x01'}; // Set raster image double width
|
||||
const char S_RASTER_2H[4] = { '\x1d', '\x76', '\x30', '\x02'}; // Set raster image double height
|
||||
const char S_RASTER_Q[4] = { '\x1d', '\x76', '\x30', '\x03'}; // Set raster image quadruple
|
||||
|
||||
};
|
||||
BIN
devices/Printers/ESC_POS/Документация/escpos_cm_en.pdf
Normal file
BIN
devices/Printers/ESC_POS/Документация/escpos_cm_en.pdf
Normal file
Binary file not shown.
BIN
devices/Printers/ESC_POS/Документация/escpospp-master.zip
Normal file
BIN
devices/Printers/ESC_POS/Документация/escpospp-master.zip
Normal file
Binary file not shown.
295
devices/Printers/ESC_POS/Документация/printer.c
Normal file
295
devices/Printers/ESC_POS/Документация/printer.c
Normal file
@ -0,0 +1,295 @@
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "serial.h"
|
||||
#include "printer.h"
|
||||
#include "error_private.h"
|
||||
#include "constants.h"
|
||||
|
||||
escpos_printer *escpos_printer_network(const char * const addr, const short port)
|
||||
{
|
||||
assert(addr != NULL);
|
||||
|
||||
int sockfd;
|
||||
escpos_printer *printer = NULL;
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) {
|
||||
last_error = ESCPOS_ERROR_SOCK;
|
||||
} else {
|
||||
struct sockaddr_in dest;
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = htons(port);
|
||||
|
||||
if (inet_pton(AF_INET, addr, &dest.sin_addr.s_addr) == 0) {
|
||||
last_error = ESCPOS_ERROR_INVALID_ADDR;
|
||||
} else if (connect(sockfd, (struct sockaddr*)&dest, sizeof(dest)) != 0) {
|
||||
last_error = ESCPOS_ERROR_CONNECTION_FAILED;
|
||||
} else {
|
||||
printer = (escpos_printer *)malloc(sizeof(escpos_printer));
|
||||
printer->sockfd = sockfd;
|
||||
printer->config.max_width = ESCPOS_MAX_DOT_WIDTH;
|
||||
printer->config.chunk_height = ESCPOS_CHUNK_DOT_HEIGHT;
|
||||
printer->config.is_network_printer = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return printer;
|
||||
}
|
||||
|
||||
escpos_printer *escpos_printer_serial(const char * const portname, const int baudrate)
|
||||
{
|
||||
assert(portname != NULL);
|
||||
|
||||
int serialfd;
|
||||
escpos_printer *printer = NULL;
|
||||
|
||||
serialfd = open(portname, O_WRONLY | O_NOCTTY | O_SYNC);
|
||||
|
||||
if (serialfd < 0) {
|
||||
last_error = ESCPOS_ERROR_SOCK;
|
||||
} else {
|
||||
set_interface_attribs(serialfd, baudrate);
|
||||
|
||||
printer = (escpos_printer *)malloc(sizeof(escpos_printer));
|
||||
printer->sockfd = serialfd;
|
||||
printer->config.max_width = ESCPOS_MAX_DOT_WIDTH;
|
||||
printer->config.chunk_height = ESCPOS_CHUNK_DOT_HEIGHT;
|
||||
printer->config.is_network_printer = 0;
|
||||
}
|
||||
|
||||
return printer;
|
||||
}
|
||||
|
||||
int escpos_printer_config(escpos_printer *printer, const escpos_config * const config)
|
||||
{
|
||||
assert(printer != NULL);
|
||||
assert(config != NULL);
|
||||
|
||||
printer->config = *config;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void escpos_printer_destroy(escpos_printer *printer)
|
||||
{
|
||||
assert(printer != NULL);
|
||||
|
||||
close(printer->sockfd);
|
||||
free(printer);
|
||||
}
|
||||
|
||||
int escpos_printer_raw(escpos_printer *printer, const char * const message, const int len)
|
||||
{
|
||||
assert(printer != NULL);
|
||||
|
||||
int total = len;
|
||||
int sent = 0;
|
||||
int bytes = 0;
|
||||
|
||||
if (printer->config.is_network_printer) {
|
||||
// Network printer logic.
|
||||
// Make sure send() sends all data
|
||||
while (sent < total) {
|
||||
bytes = send(printer->sockfd, message, total, 0);
|
||||
if (bytes == -1) {
|
||||
last_error = ESCPOS_ERROR_SEND_FAILED;
|
||||
break;
|
||||
} else {
|
||||
sent += bytes;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Serial printer logic.
|
||||
sent = write(printer->sockfd, message, len);
|
||||
if (sent != len) {
|
||||
last_error = ESCPOS_ERROR_SEND_FAILED;
|
||||
}
|
||||
tcdrain(printer->sockfd);
|
||||
}
|
||||
|
||||
return !(sent == total);
|
||||
}
|
||||
|
||||
int escpos_printer_cut(escpos_printer *printer, const int lines)
|
||||
{
|
||||
char buffer[4];
|
||||
strncpy(buffer, ESCPOS_CMD_CUT, 3);
|
||||
buffer[3] = lines;
|
||||
return escpos_printer_raw(printer, buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
int escpos_printer_feed(escpos_printer *printer, const int lines)
|
||||
{
|
||||
assert(lines > 0 && lines < 256);
|
||||
|
||||
char buffer[3];
|
||||
strncpy(buffer, ESCPOS_CMD_FEED, 2);
|
||||
buffer[2] = lines;
|
||||
return escpos_printer_raw(printer, buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
void set_bit(unsigned char *byte, const int i, const int bit)
|
||||
{
|
||||
assert(byte != NULL);
|
||||
assert(i >= 0 && i < 8);
|
||||
|
||||
if (bit > 0) {
|
||||
*byte |= 1 << i;
|
||||
} else {
|
||||
*byte &= ~(1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculates the padding required so that the size fits in 32 bits
|
||||
void calculate_padding(const int size, int *padding_l, int *padding_r)
|
||||
{
|
||||
assert(padding_l != NULL);
|
||||
assert(padding_r != NULL);
|
||||
|
||||
if (size % 32 == 0) {
|
||||
*padding_l = 0;
|
||||
*padding_r = 0;
|
||||
} else {
|
||||
int padding = 32 - (size % 32);
|
||||
*padding_l = padding / 2;
|
||||
*padding_r = padding / 2 + (padding % 2 == 0 ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
void convert_image_to_bits(unsigned char *pixel_bits,
|
||||
const unsigned char *image_data,
|
||||
const int w,
|
||||
const int h,
|
||||
int *bitmap_w,
|
||||
int *bitmap_h)
|
||||
{
|
||||
assert(pixel_bits != NULL);
|
||||
assert(image_data != NULL);
|
||||
assert(bitmap_w != NULL);
|
||||
assert(bitmap_h != NULL);
|
||||
|
||||
int padding_l, padding_r, padding_t, padding_b;
|
||||
calculate_padding(w, &padding_l, &padding_r);
|
||||
calculate_padding(h, &padding_t, &padding_b);
|
||||
|
||||
int padded_w = w + padding_l + padding_r;
|
||||
|
||||
// We only need to add the padding to the bottom for height.
|
||||
// This is because when printing long images, only the last
|
||||
// chunk will have the irregular height.
|
||||
padding_b += padding_t;
|
||||
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < padded_w; x++) {
|
||||
int pi = (y * padded_w) + x;
|
||||
int curr_byte = pi / 8;
|
||||
unsigned char pixel = image_data[(y * w) + x];
|
||||
int bit = y < h ? pixel < 128 : 0;
|
||||
set_bit(&pixel_bits[curr_byte], 7 - (pi % 8), bit);
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = 0; y < padding_b; y++) {
|
||||
for (int x = 0; x < padded_w; x++) {
|
||||
int pi = (h * padded_w) + (y * padded_w) + x;
|
||||
int curr_byte = pi / 8;
|
||||
set_bit(&pixel_bits[curr_byte], 7 - (pi % 8), 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Outputs the bitmap width and height after padding
|
||||
*bitmap_w = w + padding_l + padding_r;
|
||||
*bitmap_h = h + padding_b;
|
||||
}
|
||||
|
||||
int escpos_printer_print(escpos_printer *printer,
|
||||
const unsigned char *pixel_bits,
|
||||
const int w,
|
||||
const int h)
|
||||
{
|
||||
assert(printer != NULL);
|
||||
assert(pixel_bits != NULL);
|
||||
assert(w > 0 && w <= printer->config.max_width);
|
||||
assert(h > 0 && h <= printer->config.chunk_height);
|
||||
assert(w % 32 == 0);
|
||||
assert(h % 32 == 0);
|
||||
|
||||
int result = escpos_printer_raw(printer, ESCPOS_CMD_PRINT_RASTER_BIT_IMAGE, 4);
|
||||
|
||||
char buffer[4];
|
||||
buffer[0] = (((w / 8) >> 0) & 0xFF);
|
||||
buffer[1] = (((w / 8) >> 8) & 0xFF);
|
||||
buffer[2] = ((h >> 0) & 0xFF);
|
||||
buffer[3] = ((h >> 8) & 0xFF);
|
||||
result = escpos_printer_raw(printer, buffer, 4);
|
||||
result = escpos_printer_raw(printer, (char *)pixel_bits, (w / 8) * h);
|
||||
|
||||
if (result != 0) {
|
||||
last_error = ESCPOS_ERROR_IMAGE_PRINT_FAILED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int escpos_printer_image(escpos_printer *printer,
|
||||
const unsigned char * const image_data,
|
||||
const int width,
|
||||
const int height)
|
||||
{
|
||||
assert(printer != NULL);
|
||||
assert(image_data != NULL);
|
||||
assert(width > 0 && width <= printer->config.max_width);
|
||||
assert(height > 0);
|
||||
|
||||
int result = 0;
|
||||
|
||||
if (image_data != NULL) {
|
||||
int byte_width = printer->config.max_width / 8;
|
||||
|
||||
int padding_t, padding_b;
|
||||
calculate_padding(height, &padding_t, &padding_b);
|
||||
int print_height = height + padding_t + padding_b;
|
||||
|
||||
unsigned char pixel_bits[byte_width * print_height];
|
||||
|
||||
int c = 0;
|
||||
int chunks = 0;
|
||||
if (height <= printer->config.chunk_height) {
|
||||
chunks = 1;
|
||||
} else {
|
||||
chunks = (height / printer->config.chunk_height) + (height % printer->config.chunk_height ? 1 : 0);
|
||||
}
|
||||
|
||||
while (c < chunks) {
|
||||
// Because the printer's image buffer has a limited memory,
|
||||
// if the image's height exceeds config.chunk_height pixels,
|
||||
// it is printed in chunks of x * config.chunk_height pixels.
|
||||
int chunk_height = (c + 1) * printer->config.chunk_height <= height ?
|
||||
printer->config.chunk_height :
|
||||
height - (c * printer->config.chunk_height);
|
||||
|
||||
int bitmap_w, bitmap_h;
|
||||
convert_image_to_bits(
|
||||
pixel_bits,
|
||||
image_data + (c * printer->config.chunk_height * width),
|
||||
width,
|
||||
chunk_height,
|
||||
&bitmap_w,
|
||||
&bitmap_h);
|
||||
|
||||
result = escpos_printer_print(printer, pixel_bits, bitmap_w, bitmap_h);
|
||||
if (result != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
c += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
106
devices/Printers/ESC_POS/Документация/printer.h
Normal file
106
devices/Printers/ESC_POS/Документация/printer.h
Normal file
@ -0,0 +1,106 @@
|
||||
#ifndef ESCPOSPRINTER_PRINTER_H
|
||||
#define ESCPOSPRINTER_PRINTER_H
|
||||
|
||||
typedef struct escpos_config {
|
||||
// See ESCPOS_MAX_DOT_WIDTH in constants.h
|
||||
// Default value: ESCPOS_MAX_DOT_WIDTH
|
||||
int max_width;
|
||||
|
||||
// See ESCPOS_CHUNK_DOT_HEIGHT in constants.h
|
||||
// Default value: ESCPOS_CHUNK_DOT_HEIGHT
|
||||
int chunk_height;
|
||||
|
||||
unsigned int is_network_printer : 1;
|
||||
} escpos_config;
|
||||
|
||||
typedef struct escpos_printer {
|
||||
int sockfd;
|
||||
escpos_config config;
|
||||
} escpos_printer;
|
||||
|
||||
// Connects to an ESC/POS printer via network
|
||||
//
|
||||
// Params:
|
||||
// - addr: the printer's address
|
||||
// - port: the printer's port
|
||||
//
|
||||
// Return value: the printer object if successful, NULL otherwise.
|
||||
// If it fails, use escpos_last_error() to get the error code.
|
||||
extern escpos_printer *escpos_printer_network(const char * const addr, const short port);
|
||||
|
||||
// Connects to an ESC/POS printer via serial
|
||||
//
|
||||
// Params:
|
||||
// - portname: the path to the serial file to be used
|
||||
// - baudrate: the baudrate for serial communication
|
||||
//
|
||||
// Return value: the printer object if successful, NULL otherwise.
|
||||
// If it fails, use escpos_last_error() to get the error code.
|
||||
extern escpos_printer *escpos_printer_serial(const char * const portname, const int baudrate);
|
||||
|
||||
// Modifies the printer's configuration
|
||||
//
|
||||
// Params:
|
||||
// - printer: the printer
|
||||
// - config: the config
|
||||
//
|
||||
// Return value: 0 is successful, non-zero otherwise.
|
||||
// If it fails, use escpos_last_error() to get the error code.
|
||||
extern int escpos_printer_config(escpos_printer *printer, const escpos_config * const config);
|
||||
|
||||
// Destroys the printer and deallocates its memory
|
||||
//
|
||||
// Params:
|
||||
// - printer: the printer
|
||||
extern void escpos_printer_destroy(escpos_printer *printer);
|
||||
|
||||
// Sends raw data to the printer
|
||||
//
|
||||
// Params:
|
||||
// - printer: the printer
|
||||
// - message: the data
|
||||
// - len: the length of the data in bytes
|
||||
//
|
||||
// Return value: 0 is successful, non-zero otherwise.
|
||||
// If it fails, use escpos_last_error() to get the error code.
|
||||
extern int escpos_printer_raw(escpos_printer *printer, const char * const message, const int len);
|
||||
|
||||
// Cuts the paper
|
||||
//
|
||||
// Params:
|
||||
// - printer: the printer
|
||||
// - lines: no. of lines to feed before cutting
|
||||
//
|
||||
// Return value: 0 is successful, non-zero otherwise.
|
||||
// If it fails, use escpos_last_error() to get the error code.
|
||||
extern int escpos_printer_cut(escpos_printer *printer, const int lines);
|
||||
|
||||
// Feeds n lines
|
||||
//
|
||||
// Params:
|
||||
// - printer: the printer
|
||||
// - lines: no. of lines
|
||||
//
|
||||
// Return value: 0 is successful, non-zero otherwise.
|
||||
// If it fails, use escpos_last_error() to get the error code.
|
||||
extern int escpos_printer_feed(escpos_printer *printer, const int lines);
|
||||
|
||||
// Prints an image
|
||||
//
|
||||
// NOTE: This function will send the image data to the printer's buffer
|
||||
// before sending the print command, instead of printing the image directly.
|
||||
//
|
||||
// Params:
|
||||
// - printer: the printer
|
||||
// - image_data: an array of width * height bytes containing the pixels in grayscale
|
||||
// - width: the image width (must be at most 512)
|
||||
// - height: the image height
|
||||
//
|
||||
// Return value: 0 is successful, non-zero otherwise.
|
||||
// If it fails, use escpos_last_error() to get the error code.
|
||||
extern int escpos_printer_image(escpos_printer *printer,
|
||||
const unsigned char * const image_data,
|
||||
const int width,
|
||||
const int height);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user