
-----------------------------------
schouwen
Mon Nov 09, 2009 12:30 pm

Simulation of parallel put without a parallel port
-----------------------------------
I have coded up a module that allows the parallel port to be simulated graphically on-screen. This will allow those who don't have access to a parallel port at home to still be able to test school assignments that use it. This module actually offers both access to the real parallel port in addition to the simulation environment so that your programs require just one change in the call to PpDim.intialize().

Hopefully other will improve on it. If anyone knows of a better place to post the module and its future modifications, could you please let me know. I would like to make this code more easily accessible to everyone. In the meantime, here is the source code for file ParallelPortDIM.t and its test driver "PpDIM TestDriver.t"



ParallelPortDIM.t:
===========
module PpDim

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Parallel Port Device Interface Module
%
% Role/Responsibility:
%   This module can be used to test programs that use the parallel
%   port (that typically would have used parallelput and
%   parallelget) even if a parallel port isn't always available.
%
%   This module acts as an abstract interface to the parallelput
%   and parallelget procedures such that the real parallel port can
%   be used when it is available; otherwise, a simulated parallel
%   port can be easily interchanged. Instead of calling parallelget,
%   call PpDim.input. Similarly, instead of calling parallelput,
%   call PpDim.output.
%
%   In the simulated environment, the status of the 8 output pins
%   on the D-24 connector are indicated by graphical LEDs in a window
%   on the screen that is separate from the main program window(s).
%   Another separate window is used for setting the 5 input pins
%   on the simulated D-24 connector.
%
% Secret: How to control and read the parallel port pins.
%
% Important:
%   To use this module, include the following statements near the
%   top of your program:
%     import GUI
%     include "ParallelPortDIM.t"
%
%   Make sure that file ParallelPortDIM.t is located in the same
%   directory as your own program file; otherwise you will need to
%   modify the include statement above.
%
%   Before using any other interface procedure, first call
%   PpDim.initialize(). To use the real parallel port, call
%   PpDim.initialize(0). To use the simulator, call
%   PpDim.initialize(1).
%
% Modification History:
%  Date       Author             Reason
%  ---------- -----------------  -----------------------------
%  2009-11-01 John van Schouwen  Created initial version.
%  2009-11-09 John van Schouwen  Some very minor tweaks in preparation
%                                for public release.
%
% Copyright 2009 John van Schouwen
% This code may be freely copied and modified as long as any
% modified versions continue to be made publicly available
% with the same freedoms and restrictions.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  import GUI
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  export
    % Access Procedures and Functions
      initialize, output, input,
    % Constants
      numInPins, numOutPins
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


  % Exported constants
  const numOutPins: int := 8  % the number of output pins
  const numInPins : int := 5  % the number of input pins
  
  
  
  % The interface's mode of operation (see initialization())
  var dimMode: int
  var portOutState : int  % Output port pin (bit) states
                          % for bits 0 - 7
                          
  % Input port pin (bit) states for bits 0 - 4                        
  var portInState : array 0..(numInPins-1) of boolean
  
  var portInValue: int  % Binary value of the portInState bits
  
  % Simulation window size definitions
  var simOutWin: int
  var simInWin : int
  const simWidth:int  := 200
  const simHeight:int := 10
  
  %%%%%
  %%%%%  Input Port States window definitions  %%%%%
  %%%%%
  var portInCheckbox : array 0..(numInPins-1) of int
  var buttonInPortEnter: int

  %% Input Port States window action procedures %%
  % The first few merely set the appropriate portInState value
  % based on the checkbox that is being checked/unchecked
  procedure checkboxInBit0(value: boolean)
    portInState(0):= value
  end checkboxInBit0
  
  procedure checkboxInBit1(value: boolean)
    portInState(1):= value
  end checkboxInBit1

  procedure checkboxInBit2(value: boolean)
    portInState(2):= value
  end checkboxInBit2
  
  procedure checkboxInBit3(value: boolean)
    portInState(3):= value
  end checkboxInBit3
  
  procedure checkboxInBit4(value: boolean)
    portInState(4):= value
  end checkboxInBit4
  
  % When the "Enter" button is pressed, this action procedure
  % converts the individual portInState bit values to an 8-bit
  % binary integer value that is subsequently used by the
  % input() function.
  procedure recordPortInValue()
    portInValue:= 0
    for i:0..(numInPins-1)
      var x: int:= 0
      
      if portInState(i)
      then
        x:= 1
      end if
      portInValue:= portInValue + x*2**i
    end for
    GUI.Quit
  end recordPortInValue

 
  %%%%%
  %%%%%  Output Port States window definitions  %%%%%
  %%%%%
  
  % Draw a simulated LED in the Output Port States window
  procedure drawLed(x,y: int, colour: int, isOn: boolean)
    if isOn
    then
      Draw.FillOval(x,y,10,10,colour)
    else
      Draw.FillOval(x,y,10,10,white)
      Draw.Oval(x,y,10,10,colour)
    end if
  end drawLed
  
  % Return the Output Port States window coordinates for a given
  % led number (aka output port pin numeber). led is assumed to
  % be in the range 0 - 7.
  procedure mapLed(led:int, var x,y: int)
    x:= 375 - 50*(led - 1)
    y:= 16
  end mapLed
  
  
  
  %%%%%
  %%%%%  Exported Interface Procedures and Functions  %%%%%
  %%%%%
  

  %-----------------------------------------------------------------
  % Description:
  %   Initialize the Parallel Port DIM.
  % Arguments:
  %   mode:I - if 0, use only the real parallel port for input and
  %                  output
  %            if 1, use only the simulation windows for input and
  %                  output
  %            if 2, use both the real parallel port and simulation
  %                  window for all output, and the real parallel port
  %                  for input.
  %-----------------------------------------------------------------
  procedure initialize (mode: int)
    var prevActWin: int
    
    simInWin:= 0
    simOutWin:= 0
    portInValue:= 0
    portOutState:= 0
    if (mode < 0 or mode > 2)
    then
      put "*** PpDim Initialization error***"
      dimMode:= 1
    else
      dimMode:= mode
    end if
    
    prevActWin:= Window.GetActive()

    if mode > 0
    then
      % Setup the simulated output window for modes 1 and 2
      var x,y: int
      
      simOutWin:= Window.Open(
        "title:Output Port States,graphics:400;30,position:bottom;left")
      Window.SetActive(simOutWin)
      for i: 1..numOutPins
        mapLed(i, x, y)
        drawLed(x,y,red,false)
      end for
    end if
      
    if mode = 1
    then
      % Setup the simulated input window for mode 1
      simInWin:= Window.Open(
        "title:Input Port States,graphics:400;30,position:bottom;right")
      Window.SetActive(simInWin)
      for i: 0..(numInPins-1)
        portInState(i):= false
      end for
      portInCheckbox(0):= GUI.CreateCheckBox (375, 16, "0", checkboxInBit0)
      portInCheckbox(1):= GUI.CreateCheckBox (325, 16, "1", checkboxInBit1)
      portInCheckbox(2):= GUI.CreateCheckBox (275, 16, "2", checkboxInBit2)
      portInCheckbox(3):= GUI.CreateCheckBox (225, 16, "3", checkboxInBit3)
      portInCheckbox(4):= GUI.CreateCheckBox (175, 16, "4", checkboxInBit4)
      buttonInPortEnter:= GUI.CreateButton(0,0,0,"Enter",recordPortInValue)
      GUI.Disable(buttonInPortEnter)
      for i:0..(numInPins-1)
        GUI.Disable(portInCheckbox(i))
      end for
    end if

    Window.SetActive(prevActWin)
  end initialize
  

  %-----------------------------------------------------------------
  % Description:
  %   Return the value of the parallel port input pins or the
  %   simulation window checkboxes.
  % Returns:
  %   The value of the input pins converted to an integer value
  %   in the range 0 - 31.
  %-----------------------------------------------------------------
  function input : int
    var preActWin: int:= Window.GetActive()

    if (dimMode = 1)
    then
      Window.SetActive(simInWin)
      GUI.Enable(buttonInPortEnter)
      for i:0..(numInPins-1)
        GUI.Enable(portInCheckbox(i))
      end for
      
      loop
        exit when GUI.ProcessEvent
      end loop
      GUI.ResetQuit
      
      for i:0..(numInPins-1)
        GUI.Disable(portInCheckbox(i))
      end for
      GUI.Disable(buttonInPortEnter)
      Window.SetActive(preActWin)
      result portInValue
    else
      result parallelget
    end if
  end input
  

  %-----------------------------------------------------------------
  % Description:
  %   Output the given value to the parallel port or simulation
  %   window (or both).
  % Arguments:
  %   value:I - the value to be output. The value must be in the
  %             range 0 - 255 (8 bits). If not, nothing will happen.
  %-----------------------------------------------------------------
  procedure output(value: int)
    if (value < 0 or value > 255)
    then
      return
    end if

    portOutState:= value
 
    if (dimMode > 0)
    then
      var x, y: int
      var prevActWin: int:= Window.GetActive()
      
      Window.SetActive(simOutWin)
      for bit: 0..numOutPins-1
        mapLed(bit+1, x, y)
        drawLed(x, y, red, (portOutState div 2**bit mod 2 = 1))
      end for
      Window.SetActive(prevActWin)
    end if
    
    if (dimMode not= 1)
    then
      parallelput(value)
    end if
  end output

end PpDim % Module
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%




PpDIM TestDriver.t:
=============
% Test driver code for the PpDim module.

import GUI
include "ParallelPortDIM.t"
% Always include these two lines near the top of your program.
% The PpDim module uses the GUI module, and its source code
% is located in file PrallelPortDIM.t. (It is assumed that the
% source file is in the same directory as the "PpDim TestDriver.t"
% file.

var upperLimit: int

% Always call this before calling PpDim.input or PpDim.output
% PpDim.initialize(1) causes the on-screen simulation environment
% to be used. There will be a window of 8 LEDs for the output pins
% and a window of 5 checkboxes to allow you to enter values for
% the input pins.
PpDim.initialize(1)

% Count from 0 to 255, outputing the value in binary form to
% the 8 output pins of the "parallel port."
for i:0..255
  PpDim.output(i) % Use this instead of parallelput()
end for

loop
  % Read the parallel port input pins
  upperLimit:= PpDim.input  % Use this instead of parallelget()
  
  % Interpreting the input pins as a 5 bit binary number, count
  % from 0 to the number read from the parallel port, outputing
  % the result to the output pins of the parallel port.
  for i: 0..upperLimit
    PpDim.output(i)
    delay(100)
  end for

end loop




-----------------------------------
schouwen
Mon Nov 09, 2009 12:34 pm

Re: Simulation of parallel put without a parallel port
-----------------------------------
That was silly. I should have attached the files. So, here there are as attachments.
