Uncategorized
1

I am a very beginner on programming and raspberry usage, tho I think I learn fast. I am trying to convert an old program (not mine) that was written for Linux on C++ for communication with a printer chip using a standard serial port, into a python program with access to the same chip using GPIO ports. However, I am unable to understand how to translate the outb() portion of the code. To make things easier to understand, here is an example of the code (using real parts of the code, tho the code is actually way bigger):

#include <insert_all_necessary_libraries_here>
#include <lets_assume_there_is_no_error_here>

#define LPT 0x378       /*Port Addres(0x378,0x3BC,0x278)*/
#define PORT_OUT LPT+0  /*OUTPUT: Data port*/

int portdata;
int syncmask = 0x01;
int powermask = 0xE0;

void resetport(){
    outb(0,PORT_OUT);
}

void powerup(){
    portdata=portdata | powermask;
    outb(portdata,PORT_OUT);
}

void syncup(){
    portdata=portdata | syncmask;
    outb(portdata,PORT_OUT);
}

void syncdown(){
    portdata=portdata & (syncmask ^ 0xff);
    outb(portdata,PORT_OUT);
}

void main() {
    resetport();
    delay500us();
    powerup();
    syncdown();
    delay500us();
    syncup();
    delay500us();
}

As you can see, the code is based pretty much on the outb() command. I have a basic understanding of the function of this command and therefore I understand -somewhat- what the code is doing, tho how to do an equivalent job on python using GPIOs….. Looking at the answer from Malvineous on this answer for pretty much the same question I assume that it is indeed possible (at least using C++, not sure about Python). Nonetheless, I can’t really understand the implementation on the example given, and the links provided on that answer are not anymore (well, the answer is from 7 years ago, what was I expecting…?)

Can someone please help me out with this one? I have been trying to get this thing to work on my own for the last couple of weeks, but I have not been successful yet, and I am running out of options on how to make this work, at least with my current understanding.

(In case you want to take a look at the original code, you can download it here)

Thanks in advance to anyone that can help!

 New contributor
  • Raspberry Pi has serial ports. Can you use that? instructables.com/id/… – Brick yesterday
  • It is a bit confusing that you say it is a serial port, but you are sending 8 bit data out. For Arduino like MPU, there are write port function that can send a databyte to 8 GPIO pins. For Rpi, we need to write our own write port function (not difficult though). If you can let us know the printer schematic and/or printer IC chip, then we can make less wrong guesses. – tlfong01 yesterday   
  • What exactly do you want to achieve? Send data to a standard printer? Use the parallel port for something different? – RalfFriedl 23 hours ago
  • Your original code link seems wrong. – tlfong01 22 hours ago   
  • Why do you want to convert to Python? If you have a working C++ program, why not port that directly as C++? There’s nothing especially good about Python to make it worth re-inventing this wheel that you seem to have (mostly) already. – Brick 12 hours ago

0

Question

Convert linux C++ printer program to Rpi python

Answer

The slightly tricky part is that Rpi has no write 8 bit port function. So we need to DIY our own virtual 8 bit port by abstracting 8 GPIO pins as one fake 8 bit port. We can then write a fake write fake 8 bit port function, …

References

Centronics/Parallel Port Printer Cable – Wikipedia

centronics printer cable

Rpi GPIO Pinout rpi pinout

Serial to Parallel Printer Interface – Dan JulioDan Julio

What is outb() function call in Linux?

System calls are described in section 2 of the man pages: man 2 outb

void outb(unsigned char value, unsigned short int port);

Description

This family of functions is used to do low-level port input and output. The out* functions do port output, the in* functions do port input; the b-suffix functions are byte-width and the w-suffix functions word-width; the _p-suffix functions pause until the I/O completes.

Appendices

Appendix A – First Draft of Suggested Python Program

First draft

Printer Test Program Version Buggy b0.1 tlfong01 2019jun05hkt1130

# *** Import ***

import Rpi.GPIO
from time import sleep

# *** Constants and Variblles Declaration and Initialization ***

controlPort = 0x378
dataPort    = 0x379

resetByte = 0x00
synMask   = 0x01  # bit 0 (0b00000001) = clock/sync/control pulse signal
pwrMsk    = 0xe0  # bit 6 (0b01000000) = power on/off signal

# *** System control functions ***

def delay500uS(): # sleep 500uS
    ...
    return

def synUp(): # set clock pulse High
    ...
    return

def synDown(): # set clock pulse Low
    ...
    return

def sendOneDownGoingClockPulse():
    synDown()
    delay500uS()
    synUp()
    delay500uS()
    return

# *** Higher Level Write Virtual Port (abstracting 8 GPIO output ports to one 8 bit Arduino like output port) ***

def writePort(dataByte, controlPort):
    synDown()
    # set High or Low according to dataByte GPIO output pins 13, 14, 15, 16, 17, 18, 19 (arbitrary assigned)
    synUp()
    return

def resetPrinter():
    dataByte = resetByte
    writePort(dataByte, controlPort)
    return

def powerOnPrinter():
    dataByte = pwrMask
    writePort(dataByte, controlPort)
    return

def printChar(dataByte):
    writePort(dataByte, dataPort)
    return   

# *** Main program to print just one character to printer ***

powerOnPrinter()
resetPrinter()
dataByte = 'A'
printChar(dataByte)

# *** End of Program ***

Appendix B – Printer Test Program Buggy Version 0.2

# parallel_printer_test_02 tlfong01 2019jun05hkt1448 ***
# Rpi3B+ stretch 2019apr08, IDLE python 3.5.3 

# *** Import ***

import Rpi.GPIO as GPIO
from time import sleep

# *****************************************************************************
# *** GPIO Functions ***
# *****************************************************************************

# *** GPIO General Setup/Cleanup Functions ***

def generalSetupGPIO():
    GPIO.setwarnings(False) 
    GPIO.setmode(GPIO.BCM)
    return

def generalCleanupGpio(): 
    GPIO.cleanup()
    return

# *** GPIO Pin Setup Putput Mode ***

def setupGpioPinOutputMode(gpioPin):
    GPIO.setup(gpioPin, GPIO.OUT)
    return

# *** GPIO Pin Set High or Low ***

def setGpioPinHigh(gpioPin):  
    GPIO.output(gpioPin, GPIO.HIGH)
    return

def setGpioPinLow(gpioPin): 
    GPIO.output(gpioPin, GPIO.LOW)
    return

# *** Init GPIO Pin Output Mode And Set Low ***

def intiGpioPinOutputModeSetLow(gpioPin):
    setGpioPinOutputMode(gpioPin)
    setGpioPinLow(gpioPin)
    return

# *** Init GPIO Pin List Output Mode And Set Low  ***

def intiGpioPinListOutputModeSetLow(gpioPinList):
    for gpioPin in gpioPinList:
       initGpioPinOutputModeSetLow(gpioPin)
    return

# *** Toggle GPIO Pin Functions ***

def toggleGpioPin(gpioPin, highSeconds, lowSeconds, toggleCount): 
    for i in range(toggleCount):
        setgpioPinHigh(gpioPin)
        sleep(highSeconds)
        setGpioPinLow(gpioPin)
        sleep.(lowSeconds)
    return

def toggleGpioPinList(gpioPinList, highSeconds, lowSeconds, toggleCount):
    for gpioP in gpioPinList:
        togglegpioPin(gpioPin, highSeconds, lowSeconds, toggleCount)
    fprint.printEndExecution(9, 27)    
    return


# *****************************************************************************
# *** Parallel Printer Configuration ***
# *****************************************************************************

controlPortPinList = [17, 18, 27, 22, 23, 24, 25,  4]
dataPortPinList    = [ 5,  6, 13, 19, 26, 16, 20, 21]

resetByte          = 0x00
clockBitHighByte   = 0x01  
clockBitLowByte    = 0x00 
powerOnByte        = 0xe0
powerOffByte       = 0x00  

# *****************************************************************************
# *** Parallel Printer Functions ***
# *****************************************************************************

def initParallelPort(gpioPinList):
    intiGpioPinListOutputModeSetLow(gpioPinList)
    return

def writeParallelPort(dataByte, gpioPinList):
    for bitCount in range(7):
        bitValue = dataByte >> bitCount
        gpioPin  = gpioPinList[bitCount]
    if bitValue == 1:
        setGpioPinHigh(gpioPin)
    elseif
        setGpioPinLow(gpioPin)
    sendControlPulse()
    return

def delay500uS(): 
    sleep(0.005)
    return

def sendControlPulse():
    writeParallelPort(clockBitLowByte, controlPortPinList)
    delay500uS()
    writeParallelPort(clockBitHighByte, controlPortPinList)
    delay500uS()
    return

def resetPrinter():
    writeParallelPort(resetByte, controlPortPinList)
    return

def powerOnPrinter():
    writeParallelPort(dataByte, controlPortPinList)
    return

def printChar(dataByte):
    writeParallelPort(dataByte, dataPortPinList)
    return  

def initPrinter():
    initParallelPort(controlPortPinList)
    initParallelPort(dataPortPinList)
    powerOnPrinter()
    resetPrinter()
    return

def printChar(dataByte):
    writeParallelPort(dataByte, dataPortPinList) 
    return

def testPrinter():
    initPrinter():
    printChar('A')
    return

# *** Main ***

testPrinter()

# *** End of Program ***

Appendix C – Printer Test Program version 0.3 tlfong01 2019jun06hkt1341

# parallel_printer_test_05 tlfong01 2019jun06hkt1148 ***
# Rpi3B+ stretch 2019apr08, python 3.5.3 

# *** Import ***

import RPi.GPIO as GPIO
from time import sleep

# *****************************************************************************
# *** GPIO Functions ***
# *****************************************************************************

# *** GPIO General Setup/Cleanup ***

def gpioGeneralSetup():
    GPIO.setwarnings(False) 
    GPIO.setmode(GPIO.BCM)
    return

def gpioGeneralCleanup(): 
    GPIO.cleanup()
    return

# *** GPIO Pin Setup Output Mode ***

def setGpioPinOutputMode(gpioPin):
    GPIO.setup(gpioPin, GPIO.OUT)
    return

# *** GPIO Pin Set High or Low ***

def setGpioPinHigh(gpioPin):  
    GPIO.output(gpioPin, GPIO.HIGH)
    return

def setGpioPinLow(gpioPin): 
    GPIO.output(gpioPin, GPIO.LOW)
    return

# *** Init GPIO Pin Output Mode And Set Low ***

def initGpioPinOutputModeSetLow(gpioPin):
    setGpioPinOutputMode(gpioPin)
    setGpioPinLow(gpioPin)
    return

# *** Init GPIO Pin List Output Mode And Set Low  ***

def intiGpioPinListOutputModeSetLow(gpioPinList):
    for gpioPin in gpioPinList:
       initGpioPinOutputModeSetLow(gpioPin)
    return

# *** Toggle GPIO Pin Functions ***

def toggleGpioPin(gpioPin, highSeconds, lowSeconds, toggleCount): 
    for i in range(toggleCount):
        setgpioPinHigh(gpioPin)
        sleep(highSeconds)
        setGpioPinLow(gpioPin)
        sleep(lowSeconds)
    return

def toggleGpioPinList(gpioPinList, highSeconds, lowSeconds, toggleCount):
    for gpioPin in gpioPinList:
        togglegpioPin(gpioPin, highSeconds, lowSeconds, toggleCount)
    return

# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

# *** Above are general GPIO functions, independent of parallel printer app ***

# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^



# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

# *** Below are parallel printer specific functions ***

# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

# *****************************************************************************
# *** Parallel Printer Configuration ***
# *****************************************************************************

controlPortPinList = [17, 18, 27, 22, 23, 24, 25,  4]
dataPortPinList    = [ 5,  6, 13, 19, 26, 16, 20, 21]

resetByte          = 0x00
clockBitHighByte   = 0x01  
clockBitLowByte    = 0x00 
powerOnByte        = 0xe0
powerOffByte       = 0x00  

# *****************************************************************************
# *** Parallel Printer Functions ***
# *****************************************************************************

def initParallelPort(gpioPinList):
    intiGpioPinListOutputModeSetLow(gpioPinList)
    return

def writeParallelPort(gpioPinList, dataByte):
    pinNum = 0
    for gpioPin in gpioPinList:
        logicLevel = dataByte & (0x01 << pinNum)
        if logicLevel == 0:
            setGpioPinLow(gpioPin)
        else:
            setGpioPinHigh(gpioPin)
        #sendControlPulse()
        pinNum = pinNum + 1
    return

def controlPulseDelay(): 
    controlPulsePeriod = 0.005
    sleep(controlPulsePeriod)
    return

def sendControlPulse():
    writeParallelPort(controlPortPinList, clockBitHighByte)
    controlPulseDelay()
    writeParallelPort(controlPortPinList, clockBitLowByte)
    controlPulseDelay()
    return

def resetPrinter():
    writeParallelPort(controlPortPinList, resetByte)
    return

def powerOnPrinter():
    writeParallelPort(controlPortPinList, powerOnByte)
    return

def printChar(dataByte):
    writeParallelPort(dataPortPinList, dataByte)
    return  

def initPrinter():
    initParallelPort(controlPortPinList)
    initParallelPort(dataPortPinList)
    powerOnPrinter()
    resetPrinter()
    return

def printDataByte(char):
    dataByte = ord(char)
    writeParallelPort(dataPortPinList, dataByte) 
    return

def testPrinter():
    print('Begin testPrinter(), ...')
    initPrinter()
    printDataByte('A')
    print('End   testPrinter().')
    return

# *** Setup ***

gpioGeneralSetup()

# *** Main ***

testPrinter()

# *** Cleanup ***

gpioGeneralCleanup()


'''
Sample output - 2019jun06hkt1325
>>> 
= RESTART: /home/pi/Python Programs/test1202/printer_test_03_2019jun0601.py =
Begin testPrinter(), ...
End   testPrinter().
>>> 
...

# *** End of Program ***

  • Thanks for the reply! I kind of get the main point of it, tho I don’t understand how is the writePort function able to write into the chip. Also, Is the output going to be the same on all 8 ports, or it’s just virtually 8 but physically 1? – dblokillo yesterday
  • Well, tell me the printer model number, or chip IC number, then I can make more informed guesses. I can draft the write port function later. – tlfong01 yesterday   
  • So I have scribbled the second draft (Appendix B). It is “a bit” buggy. You might like to debug it for me. 🙂 Please feel free to ask me any question about my buggy program. Take your time. Go slowly. I guess it might take you another couple of weeks to digest everything. So see you July. 🙂 – tlfong01 22 hours ago   

Categories: Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: