
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
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 }
Generated on Wed Jul 13 2022 19:36:17 by
