This program implements the negotiation phase and emulates a printer. It can be plugged on the parallel port of a PC. It\'s a test program

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 
00003 
00004 #include <stdarg.h>
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <string.h>
00008 
00009 #define PAR_NEGOTIATE_EXTENSIBILITY_LINK        0x80
00010 #define PAR_NEGOTIATE_REQ_EPP_MODE              0x40
00011 #define PAR_NEGOTIATE_REQ_ECP_MODE              0x10
00012 #define PAR_NEGOTIATE_REQ_ECP_RLE_MODE          0x30
00013 #define PAR_NEGOTIATE_REQ_DEV_ID_NIBBLE_MODE    0x04
00014 #define PAR_NEGOTIATE_REQ_DEV_ID_BYTE_MODE      0x05
00015 #define PAR_NEGOTIATE_REQ_DEV_ID_ECP_MODE       0x14
00016 #define PAR_NEGOTIATE_REQ_DEV_ID_ECP_RLE_MODE   0x34
00017 #define PAR_NEGOTIATE_NIBBLE_MODE               0x00
00018 #define PAR_NEGOTIATE_BYTE_MODE                 0x01
00019 
00020 /*
00021 15 nError       -> p9
00022 13 Select       -> p10
00023 12 PE           -> p11
00024 11 Busy         -> p12
00025 10 nAck         -> p13
00026 
00027  1 nStrobe      -> p14
00028 14 nAutoFeed    -> p15
00029 16 nInit        -> p16
00030 17 nSelectIn    -> p17
00031 */
00032 
00033 DigitalOut nError(p9);
00034 DigitalOut Select(p10);
00035 DigitalOut PaperOut(p11);
00036 DigitalOut Busy(p12);
00037 DigitalOut nAck(p13);
00038 
00039 DigitalIn nStrobe(p14);
00040 DigitalIn nAutoFeed(p15);
00041 DigitalIn nInit(p16);
00042 DigitalIn nSelectIn(p17);
00043 
00044 /* 
00045 D0 p30  p0.4
00046 D1 p29  p0.5
00047 D2 p8   p0.6
00048 D3 p7   p0.7
00049 D4 p6   p0.8
00050 D5 p5   p0.9
00051 D6 p28  p0.10
00052 D7 p27  p0.11
00053 */
00054 BusInOut PtrData(p30,p29,p8,p7,p6,p5,p28,p27);
00055 
00056 #define __DOUTBUFSIZE 256
00057 #define __DINBUFSIZE 256
00058 char __outstr[__DOUTBUFSIZE];
00059 char __instr[__DINBUFSIZE];
00060 
00061 Serial pc(USBTX, USBRX); // tx, rx
00062 DigitalOut myled1(LED1);
00063 DigitalOut myled2(LED2);
00064 DigitalOut myled3(LED3);
00065 DigitalOut myled4(LED4);
00066 
00067 //---------------------------------------------------------------------------------
00068 void printer_side_ecp_mode_write_data(char c)
00069 {
00070     /* Write data */
00071     Busy = 1;
00072     PtrData = c;
00073 
00074     /* Wait HostAck = L (nAutoFd) */
00075     while (nAutoFeed) {}
00076 
00077     /* Set PeriphClk = L (nAck) */
00078     nAck = 0;
00079 
00080     /* Wait HostAck = H (nAutoFd) */
00081     while (!nAutoFeed) {}
00082 
00083     /* Set PeriphClk = H (nAck) */
00084     nAck = 1;
00085 }
00086 
00087 void printer_side_ecp_mode_write_cmd(char c)
00088 {
00089     /* Wait HostAck = L (nAutoFd) */
00090     while (nAutoFeed) {}
00091 
00092     /* Write command */
00093     Busy = 0;
00094     PtrData = c;
00095 
00096     /* Set PeriphClk = L (nAck) */
00097     nAck = 0;
00098 
00099     /* Wait HostAck = H (nAutoFd) */
00100     while (!nAutoFeed) {}
00101 
00102     /* Set PeriphClk = H (nAck) */
00103     nAck = 1;
00104 }
00105 
00106 void printer_side_ecp_sendblock(char *str, int len)
00107 {
00108     PtrData.output();
00109 
00110     while (len--)
00111     {
00112         printer_side_ecp_mode_write_data(*str);
00113         ++str;
00114     }
00115 
00116     PtrData.input();
00117 }
00118 
00119 void printer_side_ecp_printf(char *str, ...)
00120 {
00121     va_list args;
00122     int len;
00123 
00124     va_start(args, str);
00125     len=vsnprintf(__outstr,__DOUTBUFSIZE,str,args);
00126     va_end(args);
00127 
00128     printer_side_ecp_sendblock(__outstr,len);
00129 }
00130 
00131 //---------------------------------------------------------------------------------
00132 void printer_side_ecprle_sendblock(char *str, int len)
00133 {
00134 int rle = 0;
00135 char c;
00136 
00137     PtrData.output();
00138 
00139     while (len--)
00140     {
00141         c = *str;
00142         while (*(++str) == c) {++rle;}
00143 
00144         if (rle != 0)
00145         {
00146             printer_side_ecp_mode_write_cmd(rle);
00147             rle = 0;
00148         }
00149         printer_side_ecp_mode_write_data(c);
00150     }
00151 
00152     PtrData.input();
00153 }
00154 
00155 void printer_side_ecprle_printf(char *str, ...)
00156 {
00157     va_list args;
00158     int len;
00159 
00160     va_start(args, str);
00161     len=vsnprintf(__outstr,__DOUTBUFSIZE,str,args);
00162     va_end(args);
00163 
00164     printer_side_ecprle_sendblock(__outstr,len);
00165 }
00166 
00167 //---------------------------------------------------------------------------------
00168 void printer_side_byte_mode_write(char c)
00169 {
00170     /* Wait HostBusy = L (nAutoFd) */
00171     while (nAutoFeed) {}
00172 
00173     PtrData = c;
00174 
00175     /* Set PtrClk = L (nAck) */
00176     nAck = 0;
00177 
00178     /* Wait HostBusy = H (nAutoFd) */
00179     while (!nAutoFeed) {}
00180 
00181     /* Set PtrClk = H (nAck) */
00182     nAck = 1;
00183 
00184     /* Wait HostClk = L (nStrobe) */
00185     while (nStrobe) {}
00186 
00187     /* Wait HostClk = H (nStrobe) */
00188     while (!nStrobe) {}
00189 }
00190 
00191 void printer_side_byte_sendblock(char *str, int len)
00192 {
00193     PtrData.output();
00194 
00195     while (len--)
00196     {
00197         printer_side_byte_mode_write(*str);
00198         ++str;
00199     }
00200 
00201     PtrData.input();
00202 }
00203 
00204 void printer_side_byte_printf(char *str, ...)
00205 {
00206     va_list args;
00207     int len;
00208 
00209     va_start(args, str);
00210     len=vsnprintf(__outstr,__DOUTBUFSIZE,str,args);
00211     va_end(args);
00212 
00213     printer_side_byte_sendblock(__outstr,len);
00214 }
00215 
00216 //---------------------------------------------------------------------------------
00217 /*
00218 Busy, PE,Select,nError   3-0,7-4
00219 */
00220 void printer_side_write_nibble(char c)
00221 {
00222     /* Wait HostBusy = L (nAutoFd) */
00223     while (nAutoFeed) {}
00224 
00225     nError   =  c & 0x01;
00226     Select   = (c & 0x02) >> 1;
00227     PaperOut = (c & 0x04) >> 2;
00228     Busy     = (c & 0x08) >> 3;
00229 
00230     /* Set PtrClk = H (nAck) */
00231     nAck = 1;
00232 
00233     /* Set PtrClk = L (nAck) */
00234     nAck = 0;
00235 
00236     /* Wait HostBusy = H (nAutoFd) */
00237     while (!nAutoFeed) {}
00238 
00239     /* Set PtrClk = H (nAck) */
00240     nAck = 1;
00241 }
00242 
00243 void printer_side_nibble_mode_write(char c)
00244 {
00245     // data available
00246     nError = 0;
00247     printer_side_write_nibble(c);       // Low
00248     printer_side_write_nibble(c >> 4);  // High
00249 
00250     nError = 0;
00251 }
00252 
00253 void printer_side_nibble_sendblock(char *str, int len)
00254 {
00255     while (len--)
00256     {
00257         printer_side_nibble_mode_write(*str);
00258         ++str;
00259     }
00260 }
00261 
00262 void printer_side_nibble_printf(char *str, ...)
00263 {
00264     va_list args;
00265     int len;
00266 
00267     va_start(args, str);
00268     len=vsnprintf(__outstr,__DOUTBUFSIZE,str,args);
00269     va_end(args);
00270 
00271     printer_side_nibble_sendblock(__outstr,len);
00272 }
00273 
00274 //---------------------------------------------------------------------------------
00275 unsigned char printer_side_read_char(void)
00276 {
00277 unsigned char c;
00278 
00279     /* When Strobe detected, set Busy */
00280     while (nStrobe) {}
00281 
00282     Busy = 1;
00283 
00284     /* Read data lines */
00285     c = PtrData;
00286 
00287     /* Send nACK pulse */
00288     Busy = 0;
00289     nAck = 0;
00290     nAck = 1;
00291 
00292     return c;
00293 }
00294 
00295 unsigned char printer_side_negotiate(void)
00296 {
00297 unsigned char c;
00298 
00299     /* Reply: Set nAck L, nERROR,PE,   Select H */
00300     nAck = 0;
00301     nError = 1;
00302     PaperOut = 1;
00303     Select = 1;
00304 
00305     /* Wait for nStrobe = L */
00306     while (nStrobe) {}
00307 
00308     /* Read extensibility byte */
00309     c = PtrData;
00310 
00311     /* Wait for nStrobe = H, nAUTOFEED = H */
00312     while (!(nStrobe & nAutoFeed)) {}
00313 
00314     // pc.printf("Host requested mode: %02X\r\n",c & 0xff);
00315 
00316        /* Reply: PE = L, 
00317     nError = L if peripheral has reverse channel data available   
00318 
00319     if requested mode is
00320         Available, Select = H
00321         Not available, Select = L
00322     */
00323 
00324     /* EPP not available */
00325     if (c == PAR_NEGOTIATE_REQ_EPP_MODE)
00326     {
00327         Select   = 0;
00328     }
00329     else
00330     {
00331         Select   = 1;
00332     }
00333 
00334     nError   = 0;
00335     PaperOut = 0;
00336     Busy     = 0;
00337     nAck     = 0;
00338     
00339     wait_us(2);
00340     
00341     /* Set nACK = H */
00342     nAck = 1;
00343 
00344     return c;
00345 }
00346 
00347 void compatibility_read(void)
00348 {
00349 unsigned char c;
00350 int i = 0;
00351 
00352     while(nInit)
00353     {
00354         c = printer_side_read_char();
00355 
00356         /* Set Busy active so that we can print the received value */
00357         Busy = 1;
00358 
00359         pc.printf("%02X ",c & 0xff);
00360         ++i;
00361         if (i == 10)
00362         {
00363             i = 0;
00364             pc.printf("\r\n");
00365         }
00366 
00367         /* Set Busy inactive so that we can receive the following bytes */
00368         Busy = 0;
00369     }
00370 }
00371 
00372 //===========================================================================
00373 int main(void)
00374 {
00375 unsigned char c;
00376 char data;
00377 int i = 0;
00378 int rle = 0;
00379 
00380     pc.printf("Printer emulator on mbed\r\n");
00381 
00382     // set the outputs to the host computer
00383     PtrData.input();
00384 
00385 state_init:
00386     myled1 = 0;
00387     myled2 = 0;
00388     myled3 = 0;
00389     myled4 = 0;
00390 
00391     while (!nInit) {}
00392 
00393     Busy = 0;
00394     nAck = 1;
00395     nError = 1;
00396     PaperOut = 0;
00397     Select = 0;
00398 
00399     if (!nStrobe)
00400     {
00401         /* Read data from PC compatibility mode */
00402         Busy = 1;
00403 
00404         /* Read data lines */
00405         pc.printf("%02X ",PtrData & 0xff);
00406         ++i;
00407         if (i == 16)
00408         {
00409             i = 0;
00410             pc.printf("\r\n");
00411         }
00412 
00413         /* Wait for nSTROBE = H */
00414         while (!nStrobe) {}
00415 
00416         /* Send nACK pulse */
00417         Busy = 0;
00418         nAck = 0;
00419         nAck = 1;
00420         goto state_init;
00421     }
00422 
00423     else if (!(nSelectIn & !nAutoFeed))
00424     {
00425         goto state_init;
00426     }
00427 
00428     /* Negotiation phase */
00429     /* PC: nSelectIn = H, nAUTOFEED = L */
00430     c = printer_side_negotiate();
00431 
00432     switch(c)
00433     {
00434         case PAR_NEGOTIATE_REQ_EPP_MODE: // Not available
00435             goto state_init;
00436 
00437         case PAR_NEGOTIATE_REQ_DEV_ID_ECP_MODE:
00438         case PAR_NEGOTIATE_REQ_ECP_MODE:
00439 state_ecp_mode:
00440             // PARPORT_CMD_ECP_INIT1
00441             // PARPORT_CMD_ECP_INIT2
00442             if (!nSelectIn) goto state_init;
00443 
00444             // PARPORT_CMD_ECP_READ
00445             if (nStrobe)
00446             {
00447                 // data available
00448                 nError = 0;
00449 
00450                 /* Acknowledge the reverse transfer request */
00451                 PaperOut = 0;
00452 
00453                 if (c == PAR_NEGOTIATE_REQ_DEV_ID_ECP_MODE)
00454                     printer_side_ecp_printf("%cSoftware printer emulator",26);
00455                 else
00456                     printer_side_ecp_printf("Hello world from printer emulator in ecp mode\n");
00457 
00458                 // End of data
00459                 nError = 1;
00460 
00461                 while (nSelectIn) {}
00462                 goto state_init;
00463             }
00464 
00465             // PARPORT_CMD_ECP_WR_CMD
00466             // PARPORT_CMD_ECP_WR_DATA
00467             if (nInit)
00468             {
00469                 /* Acknowledge the forward transfer request */
00470                 PaperOut = 1;
00471 
00472                 /* Read data from PC ecp mode */
00473                 Busy = 1;
00474 
00475                 /* Read data lines */
00476                 pc.printf("%02X ",PtrData & 0xff);
00477                 ++i;
00478                 if (i == 16)
00479                 {
00480                     i = 0;
00481                     pc.printf("\r\n");
00482                 }
00483 
00484                 Busy = 0;
00485             }
00486 
00487             goto state_ecp_mode;
00488 
00489         case PAR_NEGOTIATE_REQ_DEV_ID_ECP_RLE_MODE:
00490         case PAR_NEGOTIATE_REQ_ECP_RLE_MODE:
00491             rle = 0;
00492 state_ecp_rle_mode:
00493             // PARPORT_CMD_ECP_INIT1
00494             // PARPORT_CMD_ECP_INIT2
00495             if (!nSelectIn) goto state_init;
00496 
00497             // PARPORT_CMD_ECP_READ
00498             if (nStrobe)
00499             {
00500                 // data available
00501                 nError = 0;
00502 
00503                 /* Acknowledge the reverse transfer request */
00504                 PaperOut = 0;
00505 
00506                 if (c == PAR_NEGOTIATE_REQ_DEV_ID_ECP_RLE_MODE)
00507                     printer_side_ecprle_printf("%cSoftware printer emulator",26);
00508                 else
00509                     printer_side_ecprle_printf("Hello world from printer emulator in ecp rle mode\n");
00510 
00511                 // End of data
00512                 nError = 1;
00513 
00514                 while (nSelectIn) {}
00515                 goto state_init;
00516             }
00517 
00518             // PARPORT_CMD_ECP_WR_CMD
00519             // PARPORT_CMD_ECP_WR_DATA
00520             if (nInit)
00521             {
00522                 // PARPORT_CMD_ECP_WR_DATA
00523                 if (nAutoFeed)
00524                 {
00525                     /* Acknowledge the forward transfer request */
00526                     PaperOut = 1;
00527 
00528                     /* Read data from PC ecp mode */
00529                     Busy = 1;
00530 
00531                     /* Read data lines */
00532                     data = PtrData;
00533 
00534                     /* if previous byte was an RLE value, replicate the current byte */
00535                     if (rle != 0)
00536                     {
00537                         pc.printf("(%02X *) %02X ",rle & 0xff,data & 0xff);
00538                         rle = 0;
00539                         ++i;
00540                         if (i == 16)
00541                         {
00542                             i = 0;
00543                             pc.printf("\r\n");
00544                         }
00545                     }
00546                     else
00547                     {
00548                         pc.printf("%02X ",data & 0xff);
00549                         ++i;
00550                         if (i == 16)
00551                         {
00552                             i = 0;
00553                             pc.printf("\r\n");
00554                         }
00555                     }
00556 
00557                     Busy = 0;
00558                 }
00559                 else
00560                 {
00561                     /* Acknowledge the forward transfer request */
00562                     PaperOut = 1;
00563 
00564                     /* Read data from PC ecp mode */
00565                     Busy = 1;
00566 
00567                     /* Read data lines */
00568                     data = PtrData;
00569 
00570                     /* RLE */
00571                     if ((data & 0x80) == 0)
00572                         /* RLE command: next byte to be replicated 1 to 127 times (2-128 bytes) */
00573                         rle = data & 0x7f;
00574                     else
00575                     {
00576                         /* Address */
00577                         pc.printf("[%02X]",data & 0xff);
00578                         ++i;
00579                         if (i == 16)
00580                         {
00581                             i = 0;
00582                             pc.printf("\r\n");
00583                         }
00584                     }
00585                     Busy = 0;
00586                 }
00587             }
00588 
00589             goto state_ecp_rle_mode;
00590 
00591         case PAR_NEGOTIATE_REQ_DEV_ID_NIBBLE_MODE:
00592             if (!nInit) goto state_init;
00593             if (!nSelectIn) goto state_init;
00594 
00595             printer_side_nibble_printf("%cSoftware printer emulator",26);
00596 
00597             // End of nibble data
00598             nError = 1;
00599 
00600             while (nSelectIn) {}
00601             goto state_init;
00602 
00603         case PAR_NEGOTIATE_REQ_DEV_ID_BYTE_MODE:
00604             if (!nInit) goto state_init;
00605             if (!nSelectIn) goto state_init;
00606 
00607             printer_side_byte_printf("%cSoftware printer emulator",26);
00608 
00609             while (nSelectIn) {}
00610             goto state_init;
00611 
00612         case PAR_NEGOTIATE_NIBBLE_MODE:
00613             if (!nInit) goto state_init;
00614             if (!nSelectIn) goto state_init;
00615 
00616             printer_side_nibble_printf("Hello world from printer emulator in nibble mode\n");
00617 
00618             // End of nibble data
00619             nError = 1;
00620 
00621             while (nSelectIn) {}
00622             goto state_init;
00623 
00624         case PAR_NEGOTIATE_BYTE_MODE:
00625             if (!nInit) goto state_init;
00626             if (!nSelectIn) goto state_init;
00627 
00628             printer_side_byte_printf("Hello world from printer emulator in byte mode\n");
00629 
00630             while (nSelectIn) {}
00631             goto state_init;
00632 
00633         default:
00634             pc.printf("Mode %02X not supported\n",c & 0xff);
00635             goto state_init;
00636     }
00637 }