Hi!
I'm working on hacking the remains of a thermal label-printer at the moment.
Brother didn't publish any usable drivers for this ancient P-touch label printer, so i decided to take it apart and 'improve' it. I've replaced electronics with Arduino and can print text/graphics from arrays in my code.
Now, to make it a tiny bit more usable, i want to be able to send an image via serial to be printed.
For now i've settled to the XBM file-format which GIMP can produce. It is quite straight forward.
Here is an example of what a file with a 16x16 pixel array would look like:
#define 16x16_width 16
#define 16x16_height 16
static unsigned char 16x16_bits[] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
The plan was just to send the image as a text file via serial terminal emulator.
The printhead has 128 elements across it's whole width and i think that sending a 128 pixel wide image every time is the easiest way to cope with different media. Then it's up to me to place the graphics i want printed, in the right spot in the file. So every time i transmit data to the printer, i will send 128 pixels wide (16 bytes) and as long as i want, until the file terminates with the }-character.
So i need a piece of code that keeps watching the serial port. When it encounters the { it gets ready to receive the data. I want to read the incoming data into an array with 16 bytes.
I've tried many different approaches for the last couple of hours but i always come up with something that doesn't work or simply gets out of hand (nested switch/case into eternity)
Some of my crap code which isn't working:
byte dataArray [16] = {0};
byte runstate = 0;
char inData = 0;
byte byteCounter = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
switch (runstate) {
case 0: // First byte has not been seen in the serial buffer yet.
if (Serial.available() > 0) {
inData = Serial.read();
if (inData == '{') // First sign in data packet has been recognised. Set runstate = 1 to continue decoding.
runstate = 1;
break;
}
case 1:
inData = Serial.read();
if (inData != 'x') // If received sign is not 'x' (in 0x... then read next byte, loop another round and check again)
{
inData = Serial.read();
}
else if (inData == 'x')
runstate = 2; // x as been found in serial string. Set runstate = 2 to start decoding first digit of hex-number.
break;
case 2:
inData = Serial.read();
switch (inData) {
case '0':
dataArray[byteCounter] = 0x0;
runstate = 3;
break;
case '1':
dataArray[byteCounter] = 0x10;
runstate = 3;
break;
case '2':
dataArray[byteCounter] = 0x20;
runstate = 3;
break;
case '3':
dataArray[byteCounter] = 0x30;
runstate = 3;
break;
case '4':
dataArray[byteCounter] = 0x40;
runstate = 3;
break;
case '5':
dataArray[byteCounter] = 0x50;
runstate = 3;
break;
case '6':
dataArray[byteCounter] = 0x60;
runstate = 3;
break;
case '7':
dataArray[byteCounter] = 0x70;
runstate = 3;
break;
case '8':
dataArray[byteCounter] = 0x80;
runstate = 3;
break;
case '9':
dataArray[byteCounter] = 0x90;
runstate = 3;
break;
case 'A':
dataArray[byteCounter] = 0xA0;
runstate = 3;
break;
case 'B':
dataArray[byteCounter] = 0xB0;
runstate = 3;
break;
case 'C':
dataArray[byteCounter] = 0xC0;
runstate = 3;
break;
case 'D':
dataArray[byteCounter] = 0xD0;
runstate = 3;
break;
case 'E':
dataArray[byteCounter] = 0xE0;
runstate = 3;
break;
case 'F':
dataArray[byteCounter] = 0xF0;
runstate = 3;
break;
}
case 3: // Runstate = 3 = Decode second digit of received hex-number. Set runstate = 4 to advance decoding.
inData = Serial.read();
switch (inData) {
case '0':
dataArray[byteCounter] = dataArray[byteCounter] | 0x0;
runstate = 4;
break;
case '1':
dataArray[byteCounter] = dataArray[byteCounter] | 0x01;
runstate = 4;
break;
case '2':
dataArray[byteCounter] = dataArray[byteCounter] | 0x02;
runstate = 4;
break;
case '3':
dataArray[byteCounter] = dataArray[byteCounter] | 0x03;
runstate = 4;
break;
case '4':
dataArray[byteCounter] = dataArray[byteCounter] | 0x04;
runstate = 4;
break;
case '5':
dataArray[byteCounter] = dataArray[byteCounter] | 0x05;
runstate = 4;
break;
case '6':
dataArray[byteCounter] = dataArray[byteCounter] | 0x06;
runstate = 4;
break;
case '7':
dataArray[byteCounter] = dataArray[byteCounter] | 0x07;
runstate = 4;
break;
case '8':
dataArray[byteCounter] = dataArray[byteCounter] | 0x08;
runstate = 4;
break;
case '9':
dataArray[byteCounter] = dataArray[byteCounter] | 0x09;
runstate = 4;
break;
case 'A':
dataArray[byteCounter] = dataArray[byteCounter] | 0x0A;
runstate = 4;
break;
case 'B':
dataArray[byteCounter] = dataArray[byteCounter] | 0x0B;
runstate = 4;
break;
case 'C':
dataArray[byteCounter] = dataArray[byteCounter] | 0x0C;
runstate = 4;
break;
case 'D':
dataArray[byteCounter] = dataArray[byteCounter] | 0x0D;
runstate = 4;
break;
case 'E':
dataArray[byteCounter] = dataArray[byteCounter] | 0x0E;
runstate = 4;
break;
case 'F':
dataArray[byteCounter] = dataArray[byteCounter] | 0x0F;
runstate = 4;
break;
}
case 4:
byteCounter++;
runstate = 1;
}
Serial.print(runstate);
Serial.print(" ");
Serial.println(dataArray[0], HEX);
Serial.print(" ");
Serial.println(dataArray[1], HEX);
Serial.print(" ");
Serial.println(dataArray[2], HEX);
if (byteCounter >= 15)
{
Serial.print("END!");
while(1);
}
}
I think the right way would be to read the data into a string and then process it, but what do i do when the arriving data can be such big amount of data? The Arduino doesn't have enough RAM for receiving even a 128x128 pix image.
Please guide me in the right direction. Programming isn't my forte - electronics is.
// Per.