This is the Adafruit thermal printer, whose Arduino library is published here: http://www.ladyada.net/products/thermalprinter/. This is a basic port to mbed that needs proper testing. The first printBitmap function is implemented but not fully tested, the stream versions are not ported yet.
Dependents: SMS_LEDMatrixPrinter
Fork of AdafruitThermalPrinter by
Diff: AdafruitThermal.cpp
- Revision:
- 0:c4a48036e46f
- Child:
- 1:315c49946ded
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AdafruitThermal.cpp Sat Jun 02 12:14:31 2012 +0000 @@ -0,0 +1,391 @@ +/*************************************************** + This is a library for the Adafruit Thermal Printer + + Pick one up at --> http://www.adafruit.com/products/597 + These printers use TTL serial to communicate, 2 pins are required + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by Limor Fried/Ladyada for Adafruit Industries. + MIT license, all text above must be included in any redistribution + ****************************************************/ + +/** Ported to mbed by Ashley Mills **/ +#include "mbed.h" +#include "AdafruitThermal.h" + + +AdafruitThermal::AdafruitThermal(PinName RX_Pin, PinName TX_Pin) { + _RX_Pin = RX_Pin; + _TX_Pin = TX_Pin; +} + +void AdafruitThermal::begin(int heatTime) { + _printer = new Serial(_RX_Pin, _TX_Pin); + _printer->baud(19200); + + // The printer can't start receiving data immediately + // upon power up -- needs a moment to initialize. If + // Arduino & printer are powered from the same supply, + // they're starting simultaneously. Need to pause for + // a moment so the printer is ready for commands. + // (A more robust approach might be to wait in a loop + // issuing status commands until valid response.) + wait(0.5); + + reset(); + + // Description of print settings from page 23 of the manual: + // ESC 7 n1 n2 n3 Setting Control Parameter Command + // Decimal: 27 55 n1 n2 n3 + // Set "max heating dots", "heating time", "heating interval" + // n1 = 0-255 Max printing dots, Unit (8dots), Default: 7 (64 dots) + // n2 = 3-255 Heating time, Unit (10us), Default: 80 (800us) + // n3 = 0-255 Heating interval, Unit (10us), Default: 2 (20us) + // The more max heating dots, the more peak current will cost + // when printing, the faster printing speed. The max heating + // dots is 8*(n1+1). The more heating time, the more density, + // but the slower printing speed. If heating time is too short, + // blank page may occur. The more heating interval, the more + // clear, but the slower printing speed. + + writeBytes(27, 55); // Esc 7 (print settings) + writeBytes(20); // Heating dots (20=balance of darkness vs no jams) + writeBytes(heatTime); // Library default = 255 (max) + writeBytes(250); // Heat interval (500 uS = slower, but darker) + + // Description of print density from page 23 of the manual: + // DC2 # n Set printing density + // Decimal: 18 35 n + // D4..D0 of n is used to set the printing density. Density is + // 50% + 5% * n(D4-D0) printing density. + // D7..D5 of n is used to set the printing break time. Break time + // is n(D7-D5)*250us. + // (Unsure of the default value for either -- not documented) + + const int + printDensity = 14, // 120% (? can go higher, text is darker but fuzzy) + printBreakTime = 4; // 500 uS + writeBytes(18, 35); // DC2 # (print density) + writeBytes((printBreakTime << 5) | printDensity); +} + +// reset printer +void AdafruitThermal::reset() { + writeBytes(27, 64); +} + +// reset formatting +void AdafruitThermal::setDefault(){ + online(); + justify('L'); + inverseOff(); + doubleHeightOff(); + setLineHeight(32); + boldOff(); + underlineOff(); + setBarcodeHeight(50); + setSize('s'); +} + +void AdafruitThermal::test(){ + write('h'); + write('e'); + write('l'); + write('l'); + write('o'); + write('!'); + write('\n'); + feed(2); +} + +void AdafruitThermal::print(char *string) { + while(*string!=0) { + write(*string); + string++; + } +} + +void AdafruitThermal::testPage() { + writeBytes(18, 84); +} + +// this is the basic function for all printing, the rest is taken care of by the +// inherited Print class! +size_t AdafruitThermal::write(uint8_t c) { + if (c == 0x13) return 0; + + if (c != 0xA) + linefeedneeded = true; + else + linefeedneeded = false; + + //DBG(" 0x"); + //DBG(c, HEX); + //DBG(" ("); + + PRINTER_PRINT(c); + + return 1; + +} + +void AdafruitThermal::setBarcodeHeight(int val){ + //default is 50 + writeBytes(29, 104, val); +} + +void AdafruitThermal::printBarcode(char * text, uint8_t type) { + int i; + uint8_t c; + + delay(1000); // Need these delays else barcode doesn't always print. ??? + writeBytes(29, 107, type); // set the type first + delay(500); + // Copy string, not including NUL terminator + for(i=0; (c = text[i]); i++) PRINTER_PRINT(c); + delay(500); + PRINTER_PRINT(c); // Terminator must follow delay. ??? + + delay(3000); // For some reason we can't immediately have line feeds here + feed(2); +} + +void AdafruitThermal::writeBytes(uint8_t a) { + PRINTER_PRINT(a); +} + +void AdafruitThermal::writeBytes(uint8_t a, uint8_t b) { + PRINTER_PRINT(a); + PRINTER_PRINT(b); +} + +void AdafruitThermal::writeBytes(uint8_t a, uint8_t b, uint8_t c) { + PRINTER_PRINT(a); + PRINTER_PRINT(b); + PRINTER_PRINT(c); +} + +void AdafruitThermal::writeBytes(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { + PRINTER_PRINT(a); + PRINTER_PRINT(b); + PRINTER_PRINT(c); + PRINTER_PRINT(d); +} + +// === Character commands === + +#define INVERSE_MASK (1 << 1) +#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) + +void AdafruitThermal::setPrintMode(uint8_t mask) { + printMode |= mask; + writePrintMode(); +} +void AdafruitThermal::unsetPrintMode(uint8_t mask) { + printMode &= ~mask; + writePrintMode(); +} + +void AdafruitThermal::writePrintMode() { + writeBytes(27, 33, printMode); +} + +void AdafruitThermal::normal() { + printMode = 0; + writePrintMode(); +} + +void AdafruitThermal::inverseOn(){ + setPrintMode(INVERSE_MASK); +} + +void AdafruitThermal::inverseOff(){ + unsetPrintMode(INVERSE_MASK); +} + +void AdafruitThermal::upsideDownOn(){ + setPrintMode(UPDOWN_MASK); +} + +void AdafruitThermal::upsideDownOff(){ + unsetPrintMode(UPDOWN_MASK); +} + +void AdafruitThermal::doubleHeightOn(){ + setPrintMode(DOUBLE_HEIGHT_MASK); +} + +void AdafruitThermal::doubleHeightOff(){ + unsetPrintMode(DOUBLE_HEIGHT_MASK); +} + +void AdafruitThermal::doubleWidthOn(){ + setPrintMode(DOUBLE_WIDTH_MASK); +} + +void AdafruitThermal::doubleWidthOff(){ + unsetPrintMode(DOUBLE_WIDTH_MASK); +} + +void AdafruitThermal::strikeOn(){ + setPrintMode(STRIKE_MASK); +} + +void AdafruitThermal::strikeOff(){ + unsetPrintMode(STRIKE_MASK); +} + +void AdafruitThermal::boldOn(){ + setPrintMode(BOLD_MASK); +} + +void AdafruitThermal::boldOff(){ + unsetPrintMode(BOLD_MASK); +} + +void AdafruitThermal::justify(char value){ + uint8_t pos = 0; + + if(value == 'l' || value == 'L') pos = 0; + if(value == 'c' || value == 'C') pos = 1; + if(value == 'r' || value == 'R') pos = 2; + + writeBytes(0x1B, 0x61, pos); +} + +// Feeds by the specified number of lines +void AdafruitThermal::feed(uint8_t x){ + // The datasheet claims sending bytes 27, 100, <x> will work + // but it feeds much much more. + while (x--) + write('\n'); +} + +// Feeds by the specified number of rows of pixels +void AdafruitThermal::feedRows(uint8_t rows) { + writeBytes(27, 74, rows); +} + +void AdafruitThermal::flush() { + writeBytes(12); +} + +void AdafruitThermal::setSize(char value){ + int size = 0; + + if(value == 's' || value == 'S') size = 0; + if(value == 'm' || value == 'M') size = 10; + if(value == 'l' || value == 'L') size = 25; + + writeBytes(29, 33, size, 10); + // if (linefeedneeded) + // println("lfn"); //feed(); + //linefeedneeded = false; +} + +// Underlines of different weights can be produced: +// 0 - no underline +// 1 - normal underline +// 2 - thick underline +void AdafruitThermal::underlineOn(uint8_t weight) { + writeBytes(27, 45, weight); +} + +void AdafruitThermal::underlineOff() { + underlineOn(0); +} + +/* +void AdafruitThermal::printBitmap(int w, int h, const uint8_t *bitmap) { + if (w > 384) return; // maximum width of the printer + for (int rowStart=0; rowStart < h; rowStart += 256) { + int chunkHeight = ((h - rowStart) > 255) ? 255 : (h - rowStart); + delay(500); // Need these delays else bitmap doesn't always print. ??? + writeBytes(18, 42); + writeBytes(chunkHeight, w/8); + delay(500); + for (int i=0; i<((w/8)*chunkHeight); i++) { + PRINTER_PRINT(pgm_read_byte(bitmap + (rowStart*(w/8)) + i)); + } + delay(500); + } +} + + +void AdafruitThermal::printBitmap(int w, int h, Stream *stream) { + if (w > 384) return; // maximum width of the printer + for (int rowStart=0; rowStart < h; rowStart += 256) { + int chunkHeight = ((h - rowStart) > 255) ? 255 : (h - rowStart); + delay(500); // Need these delays else bitmap doesn't always print. ??? + writeBytes(18, 42); + writeBytes(chunkHeight, w/8); + delay(500); + for (int i=0; i<((w/8)*chunkHeight); i++) { + PRINTER_PRINT((uint8_t)stream->read()); + } + delay(500); + } +}; + +void AdafruitThermal::printBitmap(Stream *stream) { + uint8_t tmp; + uint16_t width, height; + + tmp = stream->read(); + width = (stream->read() << 8) + tmp; + + tmp = stream->read(); + height = (stream->read() << 8) + tmp; + + printBitmap(width, height, stream); +}; +*/ + +// Take the printer offline. Print commands sent after this will be +// ignored until `online` is called +void AdafruitThermal::offline(){ + writeBytes(27, 61, 0); +} + +// Take the printer back online. Subsequent print commands will be +// obeyed. +void AdafruitThermal::online(){ + writeBytes(27, 61, 1); +} + +// Put the printer into a low-energy state immediately +void AdafruitThermal::sleep() { + sleepAfter(0); +} + +// Put the printer into a low-energy state after the given number +// of seconds +void AdafruitThermal::sleepAfter(uint8_t seconds) { + writeBytes(27, 56, seconds); +} + +// Wake the printer from a low-energy state. This command will wait +// for 50ms (as directed by the datasheet) before allowing further +// commands to be send. +void AdafruitThermal::wake() { + writeBytes(255); + delay(50); +} + +////////////////////// not working? +void AdafruitThermal::tab(){ + PRINTER_PRINT(9); +} +void AdafruitThermal::setCharSpacing(int spacing) { + writeBytes(27, 32, 0, 10); +} +void AdafruitThermal::setLineHeight(int val){ + writeBytes(27, 51, val); // default is 32 +}