need help to make universal print command

Hi! I’m working on a project where I’m interfacing with an old fashion parallel printer.
I’ve asked some questions about the code at this forum before, but it’s rewritten again.
I want to make a universal print command, just like in the LiquidCrystal library.
something like:

double pi = 3.141592
myPrinter.print(value)

myPrinter.newLine();

myPrinter.print("Hello World!)

Ive managed to create two separate functions, one for numbers (maximum 8 digits for some reason?) and one for text.

Can anyone help me combine these two fuctions and hopefully get rid of the digits bug?

Here is my current code:

#define tab 9
#define line 10
#define carReturn 13
#define rst 27

#define strobe 2
#define d0 3
#define d1 4
#define d2 5
#define d3 6
#define d4 7
#define d5 8
#define d6 9
#define d7 10
#define ack 11
#define busy 12

int value = 1337;

String myString(value); 

char myTextString[] = "hello World!";

 
 
void setup() {
  Serial.begin(9600);
 
  pinMode(strobe, OUTPUT);
  pinMode(d0, OUTPUT);
  pinMode(d1, OUTPUT);
  pinMode(d2, OUTPUT);
  pinMode(d3, OUTPUT);
  pinMode(d4, OUTPUT);
  pinMode(d5, OUTPUT);
  pinMode(d6, OUTPUT);
  pinMode(d7, OUTPUT);
  pinMode(busy, INPUT);
  digitalWrite(strobe, HIGH);
}
 

void cmd(byte command) {
           while(digitalRead(busy) == HIGH) {} 
           // Convert to parallel data
           digitalWrite(d0, bitRead(command,0));
           digitalWrite(d1, bitRead(command,1));
           digitalWrite(d2, bitRead(command,2));
           digitalWrite(d3, bitRead(command,3));
           digitalWrite(d4, bitRead(command,4));
           digitalWrite(d5, bitRead(command,5));
           digitalWrite(d6, bitRead(command,6));
           digitalWrite(d7, bitRead(command,7));
                 
           digitalWrite(strobe, 0);
           delay(2);
           digitalWrite(strobe, 1);
                     
          while (digitalRead(busy) == HIGH) {}    
 
}

void PrintInt(int value) {
     String myString(value);
     //convert to parallel data
     for (int i = 0; i < sizeof(myString); i++)
         {
                  digitalWrite(d0, bitRead(myString[i],0));
                  digitalWrite(d1, bitRead(myString[i],1));
                  digitalWrite(d2, bitRead(myString[i],2));
                  digitalWrite(d3, bitRead(myString[i],3));
                  digitalWrite(d4, bitRead(myString[i],4));
                  digitalWrite(d5, bitRead(myString[i],5));
                  digitalWrite(d6, bitRead(myString[i],6));
                  digitalWrite(d7, bitRead(myString[i],7));
                  digitalWrite(strobe, 0);
                  delay(2);
                  digitalWrite(strobe, 1);
                  while (digitalRead(busy) == 1) {}
     }
} 
     
void PrintString() {
     for (int i = 0; i < sizeof(myTextString); i++)
         {
                  digitalWrite(d0, bitRead(myTextString[i],0));
                  digitalWrite(d1, bitRead(myTextString[i],1));
                  digitalWrite(d2, bitRead(myTextString[i],2));
                  digitalWrite(d3, bitRead(myTextString[i],3));
                  digitalWrite(d4, bitRead(myTextString[i],4));
                  digitalWrite(d5, bitRead(myTextString[i],5));
                  digitalWrite(d6, bitRead(myTextString[i],6));
                  digitalWrite(d7, bitRead(myTextString[i],7));
                  digitalWrite(strobe, 0);
                  delay(2);
                  digitalWrite(strobe, 1);
                  while (digitalRead(busy) == 1) {}
     }     
}


void loop()
{

    PrintInt(value);
    delay(1000);
    cmd(line);
    cmd(carReturn);
 
}

I want to make a universal print command, just like in the LiquidCrystal library.

LiquidCrystal is a class. Only methods in a class can be overloaded, to take different arguments.

When you get to the point where you are creating a class, you can have one print method that takes a variety of arguments. Until then, you need to have functions with different names.

Why not save all the trouble and write a class that derives from the Print class. Just like LiquidCrystal does. No reason to reinvent the wheel when all you have to do is extend a class that's already doing what you need.

I’ve never written a library before, and I haven’t actually edited them very much either. Is there an other way around, or do I have to just “jump in it” ?

jump in it!

here is a basic frame (I had recently derived a class from print too), many things are missing but it should get you started
ParPrinter.h

//
//    FILE: ParPrinter.h
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: parallel printer class that implements the Print interface
//    DATE: 2013-09-30
//     URL:
//
// Released to the public domain
//

#ifndef ParPrinter_h
#define ParPrinter_h

#if defined(ARDUINO) && ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif

#define PARPRINTER_VERSION "0.1.00"

#include "Print.h"

class ParPrinter: public Print
{
  public:
    ParPrinter();  // lets assume fixed pins for now, 
    size_t write(uint8_t);

  private:
    // TODO
};
#endif
// -- END OF FILE --

parprinter.cpp

//
//    FILE: parprinter.cpp
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: parallel printer class that implements the Print interface
//    DATE: 2013-09-30
//     URL:
//
// Released to the public domain
//

#include "ParPrinter.h"

ParPrinter::ParPrinter()
{
  // define pins and pinmode here
  // tip better use an array for the datapins
  // e.g.
  pinMode(strobe, OUTPUT);
  for (int i=0; i<8; i++)
  {
    pinMode(pin[i], OUTPUT);
  }
  pinMode(busy, INPUT);
}

// write() must implement the virtual write of the Print class
size_t ParPrinter::write(uint8_t data)
{
  while(digitalRead(busy) == HIGH) {} 

  for (int i=0; i<8; i++)
  {
    digitalWrite(pin[i], bitRead(data, i) );
  }
                 
  digitalWrite(strobe, LOW);
  delay(2);
  digitalWrite(strobe, HIGH);
  while (digitalRead(busy) == HIGH) {}    
 
  return 1;
}
// -- END OF FILE --

Great! I will jump straight to is as soon as I finish my homework :) But do you think this will solve the problem that I only could print 8 digit numbers?

yes, I have no parallel printer nearby to test but I drafted it a bit further (won't spoil you rprogramming fun further)

I hope it is not a homework assignment ;)

FWIW,

when the ParPrinter Class is working, you should be able to derive your real printer Class from that, with it own special commands.

Class HPLaserJet : ParPrinter
{
   ...
   formfeed() { write(0xFF); }
   graphicsMode();
   textMode();
}
or 
Class EpsonPrinter : ParPrinter
{
  ...
}

maybe the parPrinter class needs some additional generics like: OUT_OF_PAPER etc.

No, it's not homework, I just found a ton of old printer lying around at my school, and I could have as many as I want. Its an Continuous stationery printer http://en.wikipedia.org/wiki/Continuous_stationery, so I don't think I'll run out of paper. This printer have a parallel interface, but the plan is to build in an arduino inside this printer so I can just use the "Serial.print()" function from another arduino, and use this as a debugger or a console :)

We used to use a parallel printer for access logging of a main computer. S If a hacker accessed the computer, his/her IP etc was logged on paper and removing it from /var/spool/log/blabla.log did not make sense any more.

I’m currently using pin 3-10 as data pins, pin 2 as strobe and pin 11 as busy.
Is this the right way to write that?

#include "ParPrinter.h"
#define strobe 2
#define busy 11

ParPrinter::ParPrinter()
{
  // define pins and pinmode here
  // tip better use an array for the datapins
  // e.g.

  pinMode(strobe, OUTPUT);
  for (int i=0; i<8; i++)
  {
    pinMode(pin[i+3], OUTPUT);
  }
  pinMode(busy, INPUT);
}

// write() must implement the virtual write of the Print class
size_t ParPrinter::write(uint8_t data)
{
  while(digitalRead(busy) == HIGH) {} 

  for (int i=0; i<8; i++)
  {
    digitalWrite(pin[i+1], bitRead(data, i) );
  }
                 
  digitalWrite(strobe, LOW);
  delay(2);
  digitalWrite(strobe, HIGH);
  while (digitalRead(busy) == HIGH) {}    
 
  return 1;
}
// -- END OF FILE --

No. Gammon Forum : Electronics : Microprocessors : Arduino programming traps, tips and style guide ← See trap #20. pinMode() does not belong in a constructor. You have no control over when the constructor is called, relative to when init() is called.

hansibull:
I’m currently using pin 3-10 as data pins, pin 2 as strobe and pin 11 as busy.
Is this the right way to write that?

#include "ParPrinter.h"

#define strobe 2
#define busy 11

ParPrinter::ParPrinter()
{
  // define pins and pinmode here
  // tip better use an array for the datapins
  // e.g.

pinMode(strobe, OUTPUT);
  for (int i=0; i<8; i++)
  {
    pinMode(pin[i+3], OUTPUT);  <<<<<<<<  the array goes from 0…7  the value of pin[0] should be 3  ; you need to initialize the array first.
  }
  pinMode(busy, INPUT);
}

// write() must implement the virtual write of the Print class
size_t ParPrinter::write(uint8_t data)
{
  while(digitalRead(busy) == HIGH) {}

for (int i=0; i<8; i++)
  {
    digitalWrite(pin[i+1], bitRead(data, i) );
  }
                 
  digitalWrite(strobe, LOW);
  delay(2);
  digitalWrite(strobe, HIGH);
  while (digitalRead(busy) == HIGH) {}

return 1;
}
// – END OF FILE –

see remark in code

PaulS:

I want to make a universal print command, just like in the LiquidCrystal library.

LiquidCrystal is a class. Only methods in a class can be overloaded, to take different arguments.

A function doesn't have to be a class member to be overloaded.

related read - http://en.wikipedia.org/wiki/Parallel_port#Pinouts -

A function doesn't have to be a class member to be overloaded.

Oh? Can you provide an example?

Oh? Can you provide an example?

Sure.

int foo (byte x)
{
  return x & 0x0F;
}
int foo (int x)
{
  return (x >> 4) & 0x0F;
}
int foo (char* x)
{
  return atoi(x);
}

void setup ()
{
  Serial.begin (115200);
  byte x = 0x34;
  int y = 0x34;
  Serial.println (foo (x));
  Serial.println (foo (y));
  Serial.println (foo ("1234"));
}

void loop () 
{}

edited: Missed off body of "loop()".

Sure.

I think in terms of C functions and C++ methods. C does not support function overloading. I tend to forget, as I did now, that C++ has functions to, and does support function overloading. Thanks for the reminder.