mirror of https://github.com/JorjBauer/aiie
added printer support
parent
3af0b916d7
commit
32352fcc4c
@ -1,6 +1,8 @@
|
||||
apple2e.rom
|
||||
disk.rom
|
||||
parallel.rom
|
||||
*~
|
||||
*.o
|
||||
apple/applemmu-rom.h
|
||||
apple/diskii-rom.h
|
||||
apple/parallel-rom.h
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,259 @@
|
||||
#include <string.h> // memset
|
||||
#include <stdint.h>
|
||||
#include <stdio.h> // while debugging
|
||||
|
||||
#include "fx80.h"
|
||||
#include "fx80-font.h"
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
Fx80::Fx80()
|
||||
{
|
||||
clearLine();
|
||||
escapeMode = false;
|
||||
proportionalMode = false;
|
||||
carriageDot = 0;
|
||||
twoSixteenthsLineSpacing = 36; // 1/6" line spacing is the default (12 pixels)
|
||||
graphicsWidth = 960;
|
||||
ninePinGraphics = false;
|
||||
escapeModeActive = 0;
|
||||
escapeModeExpectingBytes = -1;
|
||||
escapeModeLengthByteCount = 0;
|
||||
escapeModeLength = 0;
|
||||
}
|
||||
|
||||
Fx80::~Fx80()
|
||||
{
|
||||
}
|
||||
|
||||
void Fx80::handleEscape(uint8_t c)
|
||||
{
|
||||
switch (c & 0x7F) {
|
||||
case 75: // FIXME: single-density 480 dpi graphics line
|
||||
graphicsWidth = 480;
|
||||
break;
|
||||
case 76: // FIXME: low-speed double-density graphics line
|
||||
case 89: // FIXME: high-speed double-density graphics
|
||||
graphicsWidth = 960;
|
||||
escapeModeActive = c;
|
||||
escapeModeExpectingBytes = -1;
|
||||
escapeModeLengthByteCount = 0;
|
||||
break;
|
||||
case 90: // FIXME: quadruple-density graphics
|
||||
graphicsWidth = 960 * 2;
|
||||
break;
|
||||
case 94: // FIXME: enable 9-pin graphics
|
||||
escapeModeActive = c;
|
||||
escapeModeExpectingBytes = -1;
|
||||
escapeModeLengthByteCount = 0;
|
||||
break;
|
||||
case 65: // set line spacing
|
||||
escapeModeActive = c;
|
||||
escapeModeExpectingBytes = 1;
|
||||
break;
|
||||
case 33: // FIXME: mode select
|
||||
case 35: // FIXME: enable 8-bit reception from computer
|
||||
case 37: // FIXME: pick charset from ROM
|
||||
case 38: // FIXME: define chars in RAM
|
||||
case 42: // FIXME: set vertical tabs
|
||||
case 43: // FIXME: set form length (default: 66 lines, 11 inches)
|
||||
case 68: // FIXME: reset current tabs, pitch
|
||||
case 69: // FIXME: emphasized mode on
|
||||
case 70: // FIXME: emphasized mode off
|
||||
case 71: // FIXME: double-strike on
|
||||
case 72: // FIXME: double-strike off
|
||||
case 73: // FIXME: enable printing chr[0..31] except control codes
|
||||
case 74: // FIXME: line feed immediately, n/216th of an inch
|
||||
case 77: // FIXME: elite mode (12cpi)
|
||||
case 78: // FIXME: turn on skip-over perforation
|
||||
case 79: // FIXME: turn off skip-over perforation
|
||||
case 80: // FIXME: disable elite; enable pica mode (unless compressed is enabled)
|
||||
case 81: // FIXME: cancel print buffer, set right margin
|
||||
case 82: // FIXME: select international charset
|
||||
case 83: // FIXME: script mode on
|
||||
case 84: // FIXME: script mode off
|
||||
case 85: // FIXME: unidirecitonal mode on/off
|
||||
case 87: // FIXME: expanded mode
|
||||
case 98: // FIXME: set vertical tab
|
||||
case 105: // FIXME: immediate mode on
|
||||
case 106: // FIXME: immediate reverse linefeed 1/216"
|
||||
case 108: // FIXME: set left margin
|
||||
case 112: // FIXME: turn on proportional mode
|
||||
case 115: // FIXME: print speed
|
||||
printf("unhandled escape code %d\n", c);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Fx80::handleActiveEscapeMode(uint8_t c)
|
||||
{
|
||||
switch (escapeModeActive) {
|
||||
case 76:
|
||||
case 89:
|
||||
// one column of double-density graphics
|
||||
{
|
||||
// FIXME: abstract this - second time it's being used
|
||||
uint16_t byteIdx = (carriageDot+0) / 8 + (FX80_MAXWIDTH/8) * 0;
|
||||
uint8_t bitIdx = (carriageDot+0) % 8;
|
||||
for (int i=0; i<8; i++) {
|
||||
if (c & (1 << (7-i))) {
|
||||
rowOfBits[byteIdx] |= (1 << (7-bitIdx));
|
||||
}
|
||||
byteIdx += (FX80_MAXWIDTH/8);
|
||||
}
|
||||
}
|
||||
carriageDot++;
|
||||
break;
|
||||
case 65: // set line spacing to n/72ths of an inch (n=0-85)
|
||||
twoSixteenthsLineSpacing = 3 * c;
|
||||
|
||||
break;
|
||||
default:
|
||||
printf("unhandled active escape mode %d\n", c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Fx80::input(uint8_t c)
|
||||
{
|
||||
if (escapeMode) {
|
||||
handleEscape(c);
|
||||
escapeMode = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Is this an escape mode that gets a fixed amount of input?
|
||||
if (escapeModeActive) {
|
||||
if (escapeModeExpectingBytes < 0) {
|
||||
// We're reading 2 bytes of length
|
||||
escapeModeLengthByteCount++;
|
||||
if (escapeModeLengthByteCount == 1) {
|
||||
escapeModeLength = c;
|
||||
} else {
|
||||
escapeModeLength |= (c << 8);
|
||||
escapeModeExpectingBytes = escapeModeLength;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
escapeModeExpectingBytes--;
|
||||
}
|
||||
|
||||
handleActiveEscapeMode(c);
|
||||
if (escapeModeExpectingBytes == 0) {
|
||||
escapeModeActive = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (c == 27) {
|
||||
escapeMode = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: all these also work as 128 + c
|
||||
switch (c & 0x7F) {
|
||||
case 0: // FIXME: terminate horiz/vert tab setting
|
||||
return;
|
||||
case 7: // beep
|
||||
return;
|
||||
case 8: // FIXME: "at current width" instead of this fixed-12
|
||||
if (carriageDot >= 12)
|
||||
carriageDot -= 12;
|
||||
return;
|
||||
case 9: // FIXME: HTAB
|
||||
return;
|
||||
case 10:
|
||||
lineFeed();
|
||||
return;
|
||||
case 11: // FIXME: VTAB
|
||||
return;
|
||||
case 12: // FIXME: Form Feed
|
||||
lineFeed();
|
||||
return;
|
||||
case 13:
|
||||
carriageDot = 0;
|
||||
// lineFeed(); // FIXME: this was controlled by a switch
|
||||
return;
|
||||
case 14: // FIXME: Shift Out - turns on "Expanded Mode"
|
||||
case 15: // FIXME: Shift In - turns on "Compressed Mode"
|
||||
case 17: // FIXME: DC1
|
||||
case 18: // FIXME: DC2
|
||||
case 19: // FIXME: DC3
|
||||
case 20: // FIXME: DC4
|
||||
case 24: // FIXME: cancel text in print buffer; not the same as "clear line"
|
||||
case 127: // FIXME: delete last char in the print buffer
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// normal print - send the character verbatim...
|
||||
addCharacter(c & 0x7F); // FIXME: masking high bit
|
||||
}
|
||||
|
||||
// add the given character on the line at the current carriage dot position
|
||||
void Fx80::addCharacter(uint8_t c)
|
||||
{
|
||||
uint8_t width = Fx80Font[c * 19];
|
||||
// FIXME: is 12 right for non-proportional mode?
|
||||
if (!proportionalMode)
|
||||
width = 12;
|
||||
|
||||
// Each row for this char has two bytes of bits, left-to-right, high
|
||||
// bit leftmost.
|
||||
|
||||
const uint8_t *charPtr = &Fx80Font[c * 19];
|
||||
charPtr++;
|
||||
|
||||
for (uint8_t row=0; row<9; row++) {
|
||||
// Don't print beyond end of line!
|
||||
|
||||
for (uint8_t xoff = 0; xoff < 8; xoff++) {
|
||||
|
||||
if (carriageDot+xoff >= FX80_MAXWIDTH)
|
||||
continue;
|
||||
|
||||
uint16_t byteIdx = (carriageDot+xoff) / 8 + (FX80_MAXWIDTH/8) * row;
|
||||
uint8_t bitIdx = (carriageDot+xoff) % 8;
|
||||
|
||||
// We never clear bits - it's possible to overstrike, so just add more...
|
||||
if (charPtr[2*row] & (1 << (7-xoff))) {
|
||||
rowOfBits[byteIdx] |= (1 << (7-bitIdx));
|
||||
}
|
||||
if (charPtr[2*row+1] & (1 << (7-xoff))) {
|
||||
rowOfBits[byteIdx+1] |= (1 << (7-bitIdx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
carriageDot += 12; // FIXME
|
||||
}
|
||||
|
||||
void Fx80::lineFeed()
|
||||
{
|
||||
emitLine();
|
||||
g_printer->moveDownPixels(twoSixteenthsLineSpacing / 3); // pixel estimation
|
||||
clearLine();
|
||||
}
|
||||
|
||||
void Fx80::clearLine()
|
||||
{
|
||||
memset(rowOfBits, 0, sizeof(rowOfBits));
|
||||
}
|
||||
|
||||
void Fx80::emitLine()
|
||||
{
|
||||
// FIXME: this is very wrong. Doesn't deal with line advance
|
||||
// properly. But it's good enough for debugging basic operation.
|
||||
g_printer->addLine(rowOfBits);
|
||||
}
|
||||
|
||||
void Fx80::update()
|
||||
{
|
||||
// The onscreen window needs to update regularly, and we probably
|
||||
// want to periodically flush the Teensy buffer.
|
||||
if (g_printer) {
|
||||
g_printer->update();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,75 @@
|
||||
#ifndef __FX80_H
|
||||
#define __FX80_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* maximum width, in dots, that we're supporting. The FX80 supported
|
||||
* up to 1920 ("quadruple density") -- which I'm not, b/c that's
|
||||
* overkill for what I'm doing at the moment. I'm supporting "double density"
|
||||
* (960 dots per 8-inch line).
|
||||
*
|
||||
* My general strategy here is to fill up a line with bits until the
|
||||
* printer thinks it needs to move to the next line; and then do
|
||||
* something with the bits (send them to a printer, a screen, a file,
|
||||
* whatever). This gets both graphics and text modes in one swell foop.
|
||||
*
|
||||
* There is the troublesome "9-pin graphics mode" where each column of
|
||||
* bits is > 1 byte of data; for that, we keep an extra "rowOfPin9"
|
||||
* bits, which is just a bit stream across the width. It would be
|
||||
* easier to make rowOfBits be uint16_t but it would consume more RAM,
|
||||
* and I'm trying to minimize that as I'm down to about 13k of free
|
||||
* space in the Teensy!
|
||||
*/
|
||||
|
||||
#define FX80_MAXWIDTH 960
|
||||
|
||||
#ifdef TEENSYDUINO
|
||||
class TeensyPrinter;
|
||||
#else
|
||||
class OpenCVPrinter;
|
||||
#endif
|
||||
|
||||
class Fx80 {
|
||||
public:
|
||||
Fx80();
|
||||
~Fx80();
|
||||
|
||||
void input(uint8_t c);
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
void lineFeed();
|
||||
void clearLine();
|
||||
|
||||
void addCharacter(uint8_t c);
|
||||
|
||||
void handleEscape(uint8_t c);
|
||||
void handleActiveEscapeMode(uint8_t c);
|
||||
void emitLine();
|
||||
|
||||
protected:
|
||||
bool escapeMode;
|
||||
bool proportionalMode;
|
||||
|
||||
uint16_t carriageDot; // what dot-column we are at
|
||||
|
||||
// Line spacing. 1/216th of an inch is 1/3 of a dot, which is the minimum
|
||||
// supported by the FX-80. This is usually set in terms of 72nds, and
|
||||
// it's unlikely that I'll render anything at 1/216, but might as
|
||||
// well interpret it the way the printer understands it.
|
||||
// (That means 8/72, which is a setting of 24 here, is 8 dots tall.)
|
||||
uint16_t twoSixteenthsLineSpacing;
|
||||
|
||||
uint16_t graphicsWidth;
|
||||
bool ninePinGraphics;
|
||||
uint8_t escapeModeActive;
|
||||
int32_t escapeModeExpectingBytes;
|
||||
uint8_t escapeModeLengthByteCount;
|
||||
uint16_t escapeModeLength;
|
||||
|
||||
// 9 pixel-rows of (FX80_MAXWIDTH) bits (stuffed in 8-bit bytes)
|
||||
uint8_t rowOfBits[(FX80_MAXWIDTH/8)*9];
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,50 @@
|
||||
#include "parallelcard.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "parallel-rom.h"
|
||||
#include "fx80.h"
|
||||
|
||||
ParallelCard::ParallelCard()
|
||||
{
|
||||
fx80 = new Fx80();
|
||||
}
|
||||
|
||||
ParallelCard::~ParallelCard()
|
||||
{
|
||||
}
|
||||
|
||||
void ParallelCard::Reset()
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t ParallelCard::readSwitches(uint8_t s)
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void ParallelCard::writeSwitches(uint8_t s, uint8_t v)
|
||||
{
|
||||
if (s == 0x00) {
|
||||
fx80->input(v);
|
||||
} else {
|
||||
// printf("unknown switch 0x%X\n", s);
|
||||
}
|
||||
}
|
||||
|
||||
void ParallelCard::loadROM(uint8_t *toWhere)
|
||||
{
|
||||
#ifdef TEENSYDUINO
|
||||
Serial.println("loading parallel slot rom");
|
||||
for (uint16_t i=0; i<=0xFF; i++) {
|
||||
toWhere[i] = pgm_read_byte(&romData[i]);
|
||||
}
|
||||
#else
|
||||
printf("loading parallel slot rom\n");
|
||||
memcpy(toWhere, romData, 256);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ParallelCard::update()
|
||||
{
|
||||
fx80->update();
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
#ifndef __PARALLELCARD_H
|
||||
#define __PARALLELCARD_H
|
||||
|
||||
#ifdef TEENSYDUINO
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "applemmu.h"
|
||||
#include "slot.h"
|
||||
|
||||
class Fx80;
|
||||
|
||||
class ParallelCard : public Slot {
|
||||
public:
|
||||
ParallelCard();
|
||||
virtual ~ParallelCard();
|
||||
|
||||
virtual void Reset(); // used by BIOS cold-boot
|
||||
virtual uint8_t readSwitches(uint8_t s);
|
||||
virtual void writeSwitches(uint8_t s, uint8_t v);
|
||||
virtual void loadROM(uint8_t *toWhere);
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
Fx80 *fx80;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,9 +0,0 @@
|
||||
#include "slot.h"
|
||||
|
||||
Slot::Slot()
|
||||
{
|
||||
}
|
||||
|
||||
Slot::~Slot()
|
||||
{
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
#include "opencv-printer.h"
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
#define WINDOWNAME "printer"
|
||||
|
||||
#define HEIGHT 800
|
||||
#define NATIVEWIDTH 960 // FIXME: printer can change density...
|
||||
|
||||
|
||||
//#define WIDTH 384 // emulating the teeny printer I've got
|
||||
#define WIDTH 960
|
||||
|
||||
OpenCVPrinter::OpenCVPrinter()
|
||||
{
|
||||
pixels = new Mat(HEIGHT, WIDTH, CV_8U);
|
||||
*pixels = cv::Scalar(0xFF);
|
||||
ypos = 0;
|
||||
isDirty = false;
|
||||
namedWindow(WINDOWNAME, CV_WINDOW_AUTOSIZE);
|
||||
}
|
||||
|
||||
OpenCVPrinter::~OpenCVPrinter()
|
||||
{
|
||||
delete pixels; pixels = NULL;
|
||||
}
|
||||
|
||||
void OpenCVPrinter::update()
|
||||
{
|
||||
if (isDirty) {
|
||||
imshow(WINDOWNAME, *pixels);
|
||||
isDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCVPrinter::addLine(uint8_t *rowOfBits)
|
||||
{
|
||||
isDirty = true;
|
||||
for (int yoff=0; yoff<8; yoff++) {
|
||||
// 960 pixels == 120 bytes -- FIXME
|
||||
for (int i=0; i<(NATIVEWIDTH/8); i++) {
|
||||
uint8_t bv = rowOfBits[yoff*120+i];
|
||||
for (int xoff=0; xoff<8; xoff++) {
|
||||
// scale X from "actual FX80" coordinates to "real printer" coordinates
|
||||
uint16_t actualX = (uint16_t)(((float)(i*8+xoff) * (float)WIDTH) / (float)NATIVEWIDTH);
|
||||
|
||||
uint8_t oldPixel = pixels->at<uchar>((ypos + yoff)%HEIGHT, actualX);
|
||||
uint8_t pixelColor = (bv & (1 << (7-xoff))) ? 0x00 : 0xFF;
|
||||
// Make sure to preserve any pixels we've already drawn
|
||||
pixels->at<uchar>((ypos + yoff)%HEIGHT, actualX) = ~(~oldPixel | ~pixelColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ypos >= HEIGHT) {
|
||||
ypos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCVPrinter::moveDownPixels(uint8_t p)
|
||||
{
|
||||
ypos+= p;
|
||||
if (ypos >= HEIGHT) {
|
||||
// clear page & restart
|
||||
*pixels = cv::Scalar(0xFF);
|
||||
ypos = 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
#ifndef __OPENCV_PRINTER_H
|
||||
#define __OPENCV_PRINTER_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
|
||||
#include "physicalprinter.h"
|
||||
|
||||
class OpenCVPrinter : public PhysicalPrinter {
|
||||
public:
|
||||
OpenCVPrinter();
|
||||
virtual ~OpenCVPrinter();
|
||||
|
||||
virtual void addLine(uint8_t *rowOfBits); // must be 960 pixels wide (120 bytes)
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual void moveDownPixels(uint8_t p);
|
||||
|
||||
private:
|
||||
bool isDirty;
|
||||
uint16_t ypos;
|
||||
cv::Mat *pixels;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,13 @@
|
||||
#ifndef __PHYSICALPRINTER_H
|
||||
#define __PHYSICALPRINTER_H
|
||||
|
||||
class PhysicalPrinter {
|
||||
public:
|
||||
virtual ~PhysicalPrinter() {}
|
||||
// must be 960 pixels wide (120 bytes)
|
||||
virtual void addLine(uint8_t *rowOfBits) = 0;
|
||||
virtual void update() = 0;
|
||||
virtual void moveDownPixels(uint8_t p) = 0;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1 @@
|
||||
../apple/fx80-font.h
|
@ -0,0 +1 @@
|
||||
../apple/fx80.cpp
|
@ -0,0 +1 @@
|
||||
../apple/fx80.h
|
@ -0,0 +1 @@
|
||||
../apple/parallel-rom.h
|
@ -0,0 +1 @@
|
||||
../apple/parallelcard.cpp
|
@ -0,0 +1 @@
|
||||
../apple/parallelcard.h
|
@ -0,0 +1 @@
|
||||
../physicalprinter.h
|
@ -0,0 +1,78 @@
|
||||
#include <Arduino.h>
|
||||
#include "teensy-printer.h"
|
||||
|
||||
#define WIDTH (384) // width of printer, in dots
|
||||
#define NATIVEWIDTH 960 //
|
||||
|
||||
#define RXPIN 57
|
||||
#define TXPIN 56
|
||||
|
||||
TeensyPrinter::TeensyPrinter()
|
||||
{
|
||||
ser = new SoftwareSerial(RXPIN, TXPIN, false);
|
||||
ser->begin(19200);
|
||||
char buf[6] = { 27, '@', // init command '@'
|
||||
27, '3', 8, // ESC-3 is "set line spacing"; default 30
|
||||
0 // terminator
|
||||
};
|
||||
ser->print(buf);
|
||||
}
|
||||
|
||||
TeensyPrinter::~TeensyPrinter()
|
||||
{
|
||||
delete ser;
|
||||
}
|
||||
|
||||
void TeensyPrinter::update()
|
||||
{
|
||||
}
|
||||
|
||||
void TeensyPrinter::addLine(uint8_t *rowOfBits)
|
||||
{
|
||||
static uint8_t linebuf[WIDTH/8]; // output data for one line of pixels
|
||||
|
||||
// The rowOfBits is a set of *rows* of bits. The printer needs *columns*.
|
||||
// Convert and send as necessary.
|
||||
|
||||
// Send bitmap command, followed by bitmap data, followed by linefeed?
|
||||
// ser->write(27); // set line spacing
|
||||
// ser->write('3');
|
||||
// ser->write((uint8_t)30);
|
||||
|
||||
#define DC2 18
|
||||
|
||||
// FIXME: is this 0-6, or 1-7? One of them is empty..
|
||||
// FIXME: also read this off of the print head size/line feed size?
|
||||
for (int yoff=1; yoff<8; yoff++) {
|
||||
memset(linebuf, 0, sizeof(linebuf)); // start clear...
|
||||
for (int i=0; i<(NATIVEWIDTH/8); i++) {
|
||||
uint8_t bv = rowOfBits[yoff*120+i];
|
||||
// Process the 8 bits in this byte
|
||||
for (int xoff=0; xoff<8; xoff++) {
|
||||
// scale X from "actual FX80" coordinates to "real printer" coordinates
|
||||
uint16_t actualX = (uint16_t)(((float)(i*8+xoff) * (float)WIDTH) / (float)NATIVEWIDTH);
|
||||
|
||||
if (bv & (1 << (7-xoff))) { // if it's on in the original
|
||||
// then turn it on in our copy
|
||||
uint8_t bitNum = actualX & 0x07;
|
||||
linebuf[actualX>>3] |= (1<<(7-bitNum));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send this line to the printer
|
||||
ser->write(DC2); // send this line as a bitmap
|
||||
ser->write('*');
|
||||
ser->write(1); // FIXME: height
|
||||
ser->write(48); // FIXME: width, in bytes
|
||||
for (int i=0; i<WIDTH/8; i++) {
|
||||
ser->write(linebuf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// ser->write(10); // linefeed @ the end
|
||||
}
|
||||
|
||||
void TeensyPrinter::moveDownPixels(uint8_t p)
|
||||
{
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
#ifndef __TEENSY_PRINTER_H
|
||||
#define __TEENSY_PRINTER_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
#include "physicalprinter.h"
|
||||
|
||||
class TeensyPrinter : public PhysicalPrinter {
|
||||
public:
|
||||
TeensyPrinter();
|
||||
virtual ~TeensyPrinter();
|
||||
|
||||
virtual void addLine(uint8_t *rowOfBits); // must be 960 pixels wide (120 bytes)
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual void moveDownPixels(uint8_t p);
|
||||
|
||||
private:
|
||||
uint16_t ypos;
|
||||
SoftwareSerial *ser;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue