CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Parallel printer interfacing issue

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

Parallel printer interfacing issue
PostPosted: Fri Aug 23, 2013 11:00 am     Reply with quote

Greetings fellow PIC Wizzards...

I have a project where I want to interface to a parallel printer. I figured this would be easiest for me since I have never played with USB and would rather not need to deal with two different issues at the same time.

The printer I have is a Brother HL-2040. Since I don't know where to find any driver/commands information, I'm attempting to make a parallel 'snooper' of sorts so I can try printing out a short stream of characters (0123456789) and capture the formatting commands that come out of the computer's parallel port.

I'm utilizing a PIC18F2525 and have the parallel port's D0-D7 connected to C0-C7 and Strobe is connected to External Interrupt0. I'm using the EXT_isr to capture the data and stuff it into an array. Then I just print this out to the serial port and into my computer. I have things interfaced properly and reading data but I'm getting inconsistent results with the data.

Here's a few snippets to show what I'm doing:
Code:
#define LIMIT 3600
unsigned int8 data[LIMIT];
unsigned int16 count = 0;

#int_EXT
void EXT_isr(void)
{
  data[count++] = input_c();// input data to variable
  output_toggle(PIN_A3);// just to show activity on an LED
}

ext_int_edge(0, H_TO_L);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);

for(j = 0; j <= count; j++)
{
  printf("COUNT:%lu\n\r", count);// let's see how many bytes we have
  printf("%X ", data[j]);// spit it out to computer
}


The 'count' result varies from each printout, anywhere from 1185 to 1210 plus the data is very inconsistent. I'm not sure if I'm missing Strobes or what. My crystal is running at 19.6608Mhz so I think it should be running fast enough.

Any suggestions?

Ronald
temtronic



Joined: 01 Jul 2010
Posts: 9245
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Aug 23, 2013 11:33 am     Reply with quote

Let Google be your friend ! I quickly found a ton of stuff about 'Brother HL-2040' on Google, including the owner's manual...
You should take some time and figure out which 'link' has what you need, though you should decide what the 'default' settings are for the printer ( you gotta be able to print that out, usually 'selftest' will do that.
Most 'parallel printers' will be backward compatible with the 'Centronics standard' but don't take my word for it..these days 'standards' seem to come and go very fast....

If your PIC has the 'PSP' ( parallel slave port) it should be an easy task..
also, when using any PIC pin for digital I/O mode be sure to disable ANY/ALL other peripherals attached to it (UARTS,ADC,COMP,etc...)

I did make serial->LPT adapters years ago to 'simple dot matrix printers' using a 16C84..so I know it should be quite 'do-able'.

hth
jay
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Fri Aug 23, 2013 11:48 am     Reply with quote

I've pretty much 'Googled' myself to death searching for any info on this. The printer uses a nice proprietary language and I've even sent Brother an email asking for any kind of assistance. Was totally ignored... Owner's Manuals are pretty much useless when talking about technical stuff.

All of my innies/outies have been configured properly. Creating a parallel port to send data TO the printer is an easy thing. It's just trying to capture what's being sent from the PC to the printer is being a pain.

Thanks for the reply...

Ronald
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Aug 23, 2013 12:57 pm     Reply with quote

Sounds to me like you are missing a few bytes now and then.

Not my field of expertise, but trying to learn something new I did some googling and found a user manual for the HL-2060. There on page 4-20 there are a few settings for the parallel port:
- High Speed on/off
- Bidrectional On/Off

The last one rings a bell: the famous Centronics port was upgraded to a higher speed bidirectional port IEEE 1284. From Wikipedia this can reach an actual throughput of 2Mbyte/s.
Your (close to) 20MHz clock speed will then be to slow to capture because interrupts have close to 100 instructions overhead and then the code in the interrupt itself. One way of improving this is by removing the interrupt routine and just poll the interrupt flag from main().

Another time consuming issue in your code is the array access. Calculating array addresses is a weak point in the PIC processor and takes about 15 instruction times. Much better to calculate the start address once and then have the FSR register handle each access including automatic address post-increment.

Example for capturing 500 bytes:
Code:
#include <18F2525.h>
#fuses HS, NOLVP, NOWDT
#use delay (clock=19.6608MHz)
#use rs232(baud=115200, UART1, ERRORS)


#define LIMIT 3600
unsigned int8 data[LIMIT];

#word FSR2 = getenv("SFR:FSR2L")       // Using FSR2 because we can and FSR0 is sometimes used by the CCS compiler
#byte POSTINC2 = getenv("SFR:POSTINC2")
#bit ext0_interrupt_req = getenv("BIT:INT0IF")


void main()
{
   int16 j;
   
   ext_int_edge(0, H_TO_L);
   enable_interrupts(INT_EXT);
   clear_interrupt(INT_EXT);
   
   // Load the address for storing the captured data
   FSR2 = &data[0];

   // Capture the first 500 bytes
   for (j = 0; j < 500; j++)
   {
      while (! ext0_interrupt_req);    // Wait for strobe signal
   
      POSTINC2 = input_c();            // input data to array
      output_toggle(PIN_A3);           // just to show activity on a LED
   }
   
   // Write the captured data to the serial port
   for(j = 0; j < 500; j++)
   {
     printf("%X ", data[j]);// spit it out to computer
   }   
}
This loop takes 18 instruction times to execute for capturing. At 20MHz that should give you a maximum capture frequency of 278kHz. Hopefully fast enough.

Note: most likely you can configure your printer to use the HPGL or HPGL2 protocol. That way you won't have to reverse engineer the Brother printer language.
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Fri Aug 23, 2013 2:11 pm     Reply with quote

It may well be that the data is too fast for the approach.

If the printer has a reasonable amount of RAM, some transfer data over 1MB/sec. They hold the ACK, till they are ready to take another byte. Problem is that even if there are short bursts at high speed, the code will not be able to keep up.
Your CPU clock is just under 20MHz. 5MIPS. It takes typically about 60 instructions to get into and out of an interrupt routine. Writing a byte to an array takes about 10 instructions, so 70instructions/byte = about 1/70000 sec/byte.

I have used the PIC for hardware printer buffering, and had to have hardware to hold the ACK, poll the interrupt flag instead of using a handler, and clock at 40MHz. Like this the PIC just coped.

I see Ckielstra has proposed exactly this solution while I was typing. However I'd remove the output toggle. Knocks about 10% off the speed, and raise the clock rate. Just use the internal RC clock with the PLL. Though 'borderline' sometimes for the serial, at room temperature it should be OK, and immediately allows 32MHz. Without the toggle, and with this change, you should be up around 600K/second.

Best Wishes
temtronic



Joined: 01 Jul 2010
Posts: 9245
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Aug 23, 2013 2:56 pm     Reply with quote

hmm.. rethinking this problem and have another solution without a PIC (sorry....)

Have Notepad( or other program) send "The quick brown fox...." or other message to the printer BUT have it stored into a file(usually there's an option within the printer parameters..) instead of going to the printer. Then use a file editor like 'hexedit' or similar to open the file and see what's happening.

Might be worth a try ???

hth
jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Sat Aug 24, 2013 12:45 am     Reply with quote

A couple of things missing from Ckielstra's code:
1) needs to clear the interrupt flag.
2) better to use fast_io on the port.

Another suggestion like Temtronic's, in some cases, you can say to output to serial.

As another comment, a lot of printers can emulate other types. Now some makers have their 'own brand' operation, and also support 'semi standard' driving. So (for instance ESC/P2, which is the Epson printer language, or HPGL - Hewlett Packard). Details of these languages are available on the web. I think you will find the Brother can emulate some HP printers. Much easier to use a language that is documented, than trying to snoop the data.

Best Wishes
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Mon Aug 26, 2013 8:26 am     Reply with quote

Jay, I wouldn't have thought of printing to a file but that was the trick. Just used a HEX editor on the saved file and could see all of the commands. Unfortunately, this particular printer uses GUI commands and the driver creates a bitmap before sending the data to the printer. Impossible for my PIC to simulate. So, off to find another printer for the job.

Thanks for the replies!

Ronald
temtronic



Joined: 01 Jul 2010
Posts: 9245
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Aug 26, 2013 11:09 am     Reply with quote

yeah...I know I come up with 'old school' solutions once in awhile. I'm surprised(well, maybe not...) that the printer doesn't 'emulate' something simple like basic ASCII...sigh.
I have a couple Laserjet 4s sitting here,yup, 'old school' 25 pin connector. Only 600,000 pages run through them...
Ever since 'Windows' came along, it's been a challenge talking to the 'new' stuff.
I wonder if one of the new 'wireless' printers might work for you ?

tstorm coming...signing off..

jay
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group