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
- Committer:
- jpelletier
- Date:
- 2011-05-07
- Revision:
- 0:8133df8bab0f
File content as of revision 0:8133df8bab0f:
#include "mbed.h" #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define PAR_NEGOTIATE_EXTENSIBILITY_LINK 0x80 #define PAR_NEGOTIATE_REQ_EPP_MODE 0x40 #define PAR_NEGOTIATE_REQ_ECP_MODE 0x10 #define PAR_NEGOTIATE_REQ_ECP_RLE_MODE 0x30 #define PAR_NEGOTIATE_REQ_DEV_ID_NIBBLE_MODE 0x04 #define PAR_NEGOTIATE_REQ_DEV_ID_BYTE_MODE 0x05 #define PAR_NEGOTIATE_REQ_DEV_ID_ECP_MODE 0x14 #define PAR_NEGOTIATE_REQ_DEV_ID_ECP_RLE_MODE 0x34 #define PAR_NEGOTIATE_NIBBLE_MODE 0x00 #define PAR_NEGOTIATE_BYTE_MODE 0x01 /* 15 nError -> p9 13 Select -> p10 12 PE -> p11 11 Busy -> p12 10 nAck -> p13 1 nStrobe -> p14 14 nAutoFeed -> p15 16 nInit -> p16 17 nSelectIn -> p17 */ DigitalOut nError(p9); DigitalOut Select(p10); DigitalOut PaperOut(p11); DigitalOut Busy(p12); DigitalOut nAck(p13); DigitalIn nStrobe(p14); DigitalIn nAutoFeed(p15); DigitalIn nInit(p16); DigitalIn nSelectIn(p17); /* D0 p30 p0.4 D1 p29 p0.5 D2 p8 p0.6 D3 p7 p0.7 D4 p6 p0.8 D5 p5 p0.9 D6 p28 p0.10 D7 p27 p0.11 */ BusInOut PtrData(p30,p29,p8,p7,p6,p5,p28,p27); #define __DOUTBUFSIZE 256 #define __DINBUFSIZE 256 char __outstr[__DOUTBUFSIZE]; char __instr[__DINBUFSIZE]; Serial pc(USBTX, USBRX); // tx, rx DigitalOut myled1(LED1); DigitalOut myled2(LED2); DigitalOut myled3(LED3); DigitalOut myled4(LED4); //--------------------------------------------------------------------------------- void printer_side_ecp_mode_write_data(char c) { /* Write data */ Busy = 1; PtrData = c; /* Wait HostAck = L (nAutoFd) */ while (nAutoFeed) {} /* Set PeriphClk = L (nAck) */ nAck = 0; /* Wait HostAck = H (nAutoFd) */ while (!nAutoFeed) {} /* Set PeriphClk = H (nAck) */ nAck = 1; } void printer_side_ecp_mode_write_cmd(char c) { /* Wait HostAck = L (nAutoFd) */ while (nAutoFeed) {} /* Write command */ Busy = 0; PtrData = c; /* Set PeriphClk = L (nAck) */ nAck = 0; /* Wait HostAck = H (nAutoFd) */ while (!nAutoFeed) {} /* Set PeriphClk = H (nAck) */ nAck = 1; } void printer_side_ecp_sendblock(char *str, int len) { PtrData.output(); while (len--) { printer_side_ecp_mode_write_data(*str); ++str; } PtrData.input(); } void printer_side_ecp_printf(char *str, ...) { va_list args; int len; va_start(args, str); len=vsnprintf(__outstr,__DOUTBUFSIZE,str,args); va_end(args); printer_side_ecp_sendblock(__outstr,len); } //--------------------------------------------------------------------------------- void printer_side_ecprle_sendblock(char *str, int len) { int rle = 0; char c; PtrData.output(); while (len--) { c = *str; while (*(++str) == c) {++rle;} if (rle != 0) { printer_side_ecp_mode_write_cmd(rle); rle = 0; } printer_side_ecp_mode_write_data(c); } PtrData.input(); } void printer_side_ecprle_printf(char *str, ...) { va_list args; int len; va_start(args, str); len=vsnprintf(__outstr,__DOUTBUFSIZE,str,args); va_end(args); printer_side_ecprle_sendblock(__outstr,len); } //--------------------------------------------------------------------------------- void printer_side_byte_mode_write(char c) { /* Wait HostBusy = L (nAutoFd) */ while (nAutoFeed) {} PtrData = c; /* Set PtrClk = L (nAck) */ nAck = 0; /* Wait HostBusy = H (nAutoFd) */ while (!nAutoFeed) {} /* Set PtrClk = H (nAck) */ nAck = 1; /* Wait HostClk = L (nStrobe) */ while (nStrobe) {} /* Wait HostClk = H (nStrobe) */ while (!nStrobe) {} } void printer_side_byte_sendblock(char *str, int len) { PtrData.output(); while (len--) { printer_side_byte_mode_write(*str); ++str; } PtrData.input(); } void printer_side_byte_printf(char *str, ...) { va_list args; int len; va_start(args, str); len=vsnprintf(__outstr,__DOUTBUFSIZE,str,args); va_end(args); printer_side_byte_sendblock(__outstr,len); } //--------------------------------------------------------------------------------- /* Busy, PE,Select,nError 3-0,7-4 */ void printer_side_write_nibble(char c) { /* Wait HostBusy = L (nAutoFd) */ while (nAutoFeed) {} nError = c & 0x01; Select = (c & 0x02) >> 1; PaperOut = (c & 0x04) >> 2; Busy = (c & 0x08) >> 3; /* Set PtrClk = H (nAck) */ nAck = 1; /* Set PtrClk = L (nAck) */ nAck = 0; /* Wait HostBusy = H (nAutoFd) */ while (!nAutoFeed) {} /* Set PtrClk = H (nAck) */ nAck = 1; } void printer_side_nibble_mode_write(char c) { // data available nError = 0; printer_side_write_nibble(c); // Low printer_side_write_nibble(c >> 4); // High nError = 0; } void printer_side_nibble_sendblock(char *str, int len) { while (len--) { printer_side_nibble_mode_write(*str); ++str; } } void printer_side_nibble_printf(char *str, ...) { va_list args; int len; va_start(args, str); len=vsnprintf(__outstr,__DOUTBUFSIZE,str,args); va_end(args); printer_side_nibble_sendblock(__outstr,len); } //--------------------------------------------------------------------------------- unsigned char printer_side_read_char(void) { unsigned char c; /* When Strobe detected, set Busy */ while (nStrobe) {} Busy = 1; /* Read data lines */ c = PtrData; /* Send nACK pulse */ Busy = 0; nAck = 0; nAck = 1; return c; } unsigned char printer_side_negotiate(void) { unsigned char c; /* Reply: Set nAck L, nERROR,PE, Select H */ nAck = 0; nError = 1; PaperOut = 1; Select = 1; /* Wait for nStrobe = L */ while (nStrobe) {} /* Read extensibility byte */ c = PtrData; /* Wait for nStrobe = H, nAUTOFEED = H */ while (!(nStrobe & nAutoFeed)) {} // pc.printf("Host requested mode: %02X\r\n",c & 0xff); /* Reply: PE = L, nError = L if peripheral has reverse channel data available if requested mode is Available, Select = H Not available, Select = L */ /* EPP not available */ if (c == PAR_NEGOTIATE_REQ_EPP_MODE) { Select = 0; } else { Select = 1; } nError = 0; PaperOut = 0; Busy = 0; nAck = 0; wait_us(2); /* Set nACK = H */ nAck = 1; return c; } void compatibility_read(void) { unsigned char c; int i = 0; while(nInit) { c = printer_side_read_char(); /* Set Busy active so that we can print the received value */ Busy = 1; pc.printf("%02X ",c & 0xff); ++i; if (i == 10) { i = 0; pc.printf("\r\n"); } /* Set Busy inactive so that we can receive the following bytes */ Busy = 0; } } //=========================================================================== int main(void) { unsigned char c; char data; int i = 0; int rle = 0; pc.printf("Printer emulator on mbed\r\n"); // set the outputs to the host computer PtrData.input(); state_init: myled1 = 0; myled2 = 0; myled3 = 0; myled4 = 0; while (!nInit) {} Busy = 0; nAck = 1; nError = 1; PaperOut = 0; Select = 0; if (!nStrobe) { /* Read data from PC compatibility mode */ Busy = 1; /* Read data lines */ pc.printf("%02X ",PtrData & 0xff); ++i; if (i == 16) { i = 0; pc.printf("\r\n"); } /* Wait for nSTROBE = H */ while (!nStrobe) {} /* Send nACK pulse */ Busy = 0; nAck = 0; nAck = 1; goto state_init; } else if (!(nSelectIn & !nAutoFeed)) { goto state_init; } /* Negotiation phase */ /* PC: nSelectIn = H, nAUTOFEED = L */ c = printer_side_negotiate(); switch(c) { case PAR_NEGOTIATE_REQ_EPP_MODE: // Not available goto state_init; case PAR_NEGOTIATE_REQ_DEV_ID_ECP_MODE: case PAR_NEGOTIATE_REQ_ECP_MODE: state_ecp_mode: // PARPORT_CMD_ECP_INIT1 // PARPORT_CMD_ECP_INIT2 if (!nSelectIn) goto state_init; // PARPORT_CMD_ECP_READ if (nStrobe) { // data available nError = 0; /* Acknowledge the reverse transfer request */ PaperOut = 0; if (c == PAR_NEGOTIATE_REQ_DEV_ID_ECP_MODE) printer_side_ecp_printf("%cSoftware printer emulator",26); else printer_side_ecp_printf("Hello world from printer emulator in ecp mode\n"); // End of data nError = 1; while (nSelectIn) {} goto state_init; } // PARPORT_CMD_ECP_WR_CMD // PARPORT_CMD_ECP_WR_DATA if (nInit) { /* Acknowledge the forward transfer request */ PaperOut = 1; /* Read data from PC ecp mode */ Busy = 1; /* Read data lines */ pc.printf("%02X ",PtrData & 0xff); ++i; if (i == 16) { i = 0; pc.printf("\r\n"); } Busy = 0; } goto state_ecp_mode; case PAR_NEGOTIATE_REQ_DEV_ID_ECP_RLE_MODE: case PAR_NEGOTIATE_REQ_ECP_RLE_MODE: rle = 0; state_ecp_rle_mode: // PARPORT_CMD_ECP_INIT1 // PARPORT_CMD_ECP_INIT2 if (!nSelectIn) goto state_init; // PARPORT_CMD_ECP_READ if (nStrobe) { // data available nError = 0; /* Acknowledge the reverse transfer request */ PaperOut = 0; if (c == PAR_NEGOTIATE_REQ_DEV_ID_ECP_RLE_MODE) printer_side_ecprle_printf("%cSoftware printer emulator",26); else printer_side_ecprle_printf("Hello world from printer emulator in ecp rle mode\n"); // End of data nError = 1; while (nSelectIn) {} goto state_init; } // PARPORT_CMD_ECP_WR_CMD // PARPORT_CMD_ECP_WR_DATA if (nInit) { // PARPORT_CMD_ECP_WR_DATA if (nAutoFeed) { /* Acknowledge the forward transfer request */ PaperOut = 1; /* Read data from PC ecp mode */ Busy = 1; /* Read data lines */ data = PtrData; /* if previous byte was an RLE value, replicate the current byte */ if (rle != 0) { pc.printf("(%02X *) %02X ",rle & 0xff,data & 0xff); rle = 0; ++i; if (i == 16) { i = 0; pc.printf("\r\n"); } } else { pc.printf("%02X ",data & 0xff); ++i; if (i == 16) { i = 0; pc.printf("\r\n"); } } Busy = 0; } else { /* Acknowledge the forward transfer request */ PaperOut = 1; /* Read data from PC ecp mode */ Busy = 1; /* Read data lines */ data = PtrData; /* RLE */ if ((data & 0x80) == 0) /* RLE command: next byte to be replicated 1 to 127 times (2-128 bytes) */ rle = data & 0x7f; else { /* Address */ pc.printf("[%02X]",data & 0xff); ++i; if (i == 16) { i = 0; pc.printf("\r\n"); } } Busy = 0; } } goto state_ecp_rle_mode; case PAR_NEGOTIATE_REQ_DEV_ID_NIBBLE_MODE: if (!nInit) goto state_init; if (!nSelectIn) goto state_init; printer_side_nibble_printf("%cSoftware printer emulator",26); // End of nibble data nError = 1; while (nSelectIn) {} goto state_init; case PAR_NEGOTIATE_REQ_DEV_ID_BYTE_MODE: if (!nInit) goto state_init; if (!nSelectIn) goto state_init; printer_side_byte_printf("%cSoftware printer emulator",26); while (nSelectIn) {} goto state_init; case PAR_NEGOTIATE_NIBBLE_MODE: if (!nInit) goto state_init; if (!nSelectIn) goto state_init; printer_side_nibble_printf("Hello world from printer emulator in nibble mode\n"); // End of nibble data nError = 1; while (nSelectIn) {} goto state_init; case PAR_NEGOTIATE_BYTE_MODE: if (!nInit) goto state_init; if (!nSelectIn) goto state_init; printer_side_byte_printf("Hello world from printer emulator in byte mode\n"); while (nSelectIn) {} goto state_init; default: pc.printf("Mode %02X not supported\n",c & 0xff); goto state_init; } }