#include "sd-card-library.h"
// -- Settings for YOU to change if you want
byte mac[] = { 0x08, 0x00, 0x28, 0x56, 0xF5, 0x4D }; // physical mac address
// The printerType controls the format of the data sent from the server
// If you're using a completely different kind of printer, change this
// to correspond to your printer's PrintProcessor implementation in the
// server.
//
// If you want to control the darkness of your printouts, append a dot and
// a number, e.g. A2-raw.240 (up to a maximum of 255).
//
// If you want to flip the vertical orientation of your printouts, append
// a number and then .flipped, e.g. A2-raw.240.flipped
const char printerType[] = "A2-raw";
const unsigned int port = 80;
const unsigned long pollingDelay = 10000; // delay between polling requests (milliseconds)
int errorLED = D7; // the red LED
int downloadLED = D5; // the amber LED
int readyLED = D6; // the green LED
/*int buttonPin = D3; // the print button*/
const uint8_t chipSelect = A2;
const uint8_t mosiPin = A5;
const uint8_t misoPin = A4;
const uint8_t clockPin = A3;
//#define DEBUG // When debug is enabled, log a bunch of stuff to the hardware Serial
// -- Everything below here can be left alone
const char sketchVersion[] = "1.0.6";
// -- Debugging
#ifdef DEBUG
void debugTimeAndSeparator() {
Serial.print(millis()); Serial.print(": ");
}
void debug(const char *a) {
debugTimeAndSeparator(); Serial.println(a);
}
#define debug2(a, b) debugTimeAndSeparator(); Serial.print(a); Serial.println(b);
#else
#define debug(a)
#define debug2(a, b)
#endif
// -- Initialize the printer ID
const byte idAddress = 0;
char printerId[17]; // the unique ID for this printer.
/*char printerId[] = "323456789qwertyu";*/
inline void initPrinterID() {
/*for(int i = 0; i < 16; i++ ) {
EEPROM.write(idAddress + i, printerId[i]);
}
Serial.print("Saved printer ID: "); Serial.println(printerId);*/
if ((EEPROM.read(idAddress) == 255) || (EEPROM.read(idAddress+1) == 255)) {
debug("Generating new ID");
randomSeed(analogRead(0) * analogRead(5));
for(int i = 0; i < 16; i += 2) {
printerId[i] = random(48, 57); // 0-9
printerId[i+1] = random(97, 122); // a-z
EEPROM.write(idAddress + i, printerId[i]);
EEPROM.write(idAddress + i+1, printerId[i+1]);
}
} else {
for(int i = 0; i < 16; i++) {
printerId[i] = (char)EEPROM.read(idAddress + i);
}
}
printerId[16] = '\0';
debug2("ID: ", printerId);
}
// -- Initialize the LEDs
inline void initDiagnosticLEDs() {
pinMode(errorLED, OUTPUT);
pinMode(downloadLED, OUTPUT);
pinMode(readyLED, OUTPUT);
digitalWrite(errorLED, HIGH);
digitalWrite(downloadLED, HIGH);
digitalWrite(readyLED, HIGH);
delay(1000);
digitalWrite(errorLED, LOW);
digitalWrite(downloadLED, LOW);
digitalWrite(readyLED, LOW);
delay(500);
}
// -- Initialize the printer connection
#define PRINTER_WRITE(b) Serial1.write(b)
inline void initPrinter() {
debug("Initializing printer");
Serial1.begin(19200);
/*
Not sure how to set this! it's printing the first few rows ok then the rest light.
delay(2000);
Serial1.write(55); // Esc 7 (print settings)
Serial1.write(55);
Serial1.write(20); // Heating dots (20=balance of darkness vs no jams)
Serial1.write(255); // Library default = 255 (max)
Serial1.write(225); // Heat interval (500 uS = slower, but darker)*/
}
// -- Initialize the SD card
inline void initSD() {
Serial.begin(115200);
/*while (!Serial.available());*/
delay(2000);
debug("Initializing SD card");
// Initialize HARDWARE SPI with user defined chipSelect
if (!SD.begin(chipSelect)) {
debug("initialization failed!");
terminalError(2);
return;
}
}
// -- Initialize connection & DHCP
TCPClient client;
inline void initNetwork() {
debug("initialization network...");
IPAddress myIP = WiFi.localIP();
Serial.println(myIP); // prints the core's IP address
}
// -- Setup; runs once on boot.
void setup(){
#ifdef DEBUG
Serial.begin(9600);
#endif
initDiagnosticLEDs();
initPrinterID();
initSD();
initNetwork();
initPrinter();
}
// -- Check for new data and download if found
boolean downloadWaiting = false;
char cacheFilename[] = "TMP";
unsigned long content_length = 0;
boolean statusOk = false;
void checkForDownload() {
unsigned long length = 0;
content_length = 0;
statusOk = false;
#ifdef DEBUG
unsigned long start = millis();
#endif
if (SD.exists(cacheFilename)) {
if (!SD.remove(cacheFilename)) {
// Failed to clear cache.
terminalError(4);
}
}
File cache = SD.open(cacheFilename, FILE_WRITE);
debug2("Attempting to connect to ", host);
if (client.connect(host, port)) {
digitalWrite(downloadLED, HIGH);
client.print("GET "); client.print("/printer/"); client.print(printerId); client.println(" HTTP/1.0");
client.print("Host: "); client.print(host); client.print(":"); client.println(port);
client.flush();
client.print("Accept: application/vnd.exciting.printer."); client.println(printerType);
client.print("X-Printer-Version: "); client.println(sketchVersion);
client.println();
boolean parsingHeader = true;
while(client.connected()) {
while(client.available()) {
//Serial.print(client.peek(), HEX);
if (parsingHeader) {
debug("parsingHeader");
client.find((char*)"HTTP/1.1 ");
char statusCode[] = "xxx";
client.readBytes(statusCode, 3);
statusOk = (strcmp(statusCode, "200") == 0);
client.find((char*)"Content-Length: ");
char c;
while (isdigit(c = client.read())) {
content_length = content_length*10 + (c - '0');
}
debug2("Content length: ", content_length);
client.find((char*)"\n\r\n"); // the first \r may already have been read above
parsingHeader = false;
} else {
debug("Writing to SD");
cache.write(client.read());
length++;
}
}
debug("Waiting for data");
}
debug("Server disconnected");
digitalWrite(downloadLED, LOW);
// Close the connection, and flush any unwritten bytes to the cache.
client.stop();
cache.seek(0);
if (statusOk) {
if ((content_length == length) && (content_length == cache.size())) {
if (content_length > 0) {
downloadWaiting = true;
digitalWrite(readyLED, HIGH);
}
}
#ifdef DEBUG
else {
debug2("Failure, content length: ", content_length);
if (content_length != length) debug2("length: ", length);
if (content_length != cache.size()) debug2("cache: ", cache.size());
digitalWrite(errorLED, HIGH);
}
#endif
} else {
debug("Response code != 200");
recoverableError();
}
} else {
debug("Couldn't connect");
recoverableError();
}
cache.close();
#ifdef DEBUG
unsigned long duration = millis() - start;
debug2("Bytes: ", length);
debug2("Duration: ", duration);
#endif
}
void flashErrorLEDs(unsigned int times, unsigned int pause) {
while (times--) {
digitalWrite(errorLED, HIGH); delay(pause);
digitalWrite(errorLED, LOW); delay(pause);
}
}
inline void recoverableError() {
flashErrorLEDs(5, 100);
}
inline void terminalError(unsigned int times) {
flashErrorLEDs(times, 500);
digitalWrite(errorLED, HIGH);
// no point in carrying on, so do nothing forevermore:
while(true);
}
// -- Print send any data from the cache to the printer
inline void printFromDownload() {
File cache = SD.open(cacheFilename);
byte b;
while (content_length--) {
b = (byte)cache.read();
PRINTER_WRITE(b);
}
cache.close();
downloadWaiting = false;
digitalWrite(readyLED, LOW);
}
// -- Check for new data, print if the button is pressed.
void loop() {
if (downloadWaiting) {
/*bouncer.update();*/
/*if (bouncer.read() == HIGH) {*/
printFromDownload();
/*}*/
} else {
checkForDownload();
if (!downloadWaiting) {
delay(pollingDelay);
}
}
}