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

Files at this revision

API Documentation at this revision

Comitter:
jpelletier
Date:
Sat May 07 23:08:51 2011 +0000
Commit message:
Alpha version (may not work perfectly)

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat May 07 23:08:51 2011 +0000
@@ -0,0 +1,637 @@
+#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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sat May 07 23:08:51 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912