Engineering 15
Project
Aron Dobos
15 December 2005
Abstract
A parallel port interface between a host PC and the ADuC7026 microcontroller was implemented. A communication protocol was designed and implemented in C/C++ on both the PC and microcontroller, and the necessary hardware adaptor was built to allow the device to be connected to the standard DB-25 parallel port. With the host operating in standard parallel port (SPP) mode, data transfer rates of 83.3 kbytes/sec were achieved using full software handshaking for concurrency. The communication interface will be used in a PC-based time domain reflectometer (TDR) instrument next semester.
Microcontroller Overview
The Analog Devices ADuC7026 is a 32-bit ARM7 microcontroller designed for embedded data acquisition. It provides 4 built-in 12-bit D/A converters as well as a 12 channel 12-bit A/D converter with 1MS/s capability, as well as general purpose programmable timers, pulse width modulation, a programmable logic array (PLA), RS-232, and of course a few general purpose I/O ports. Port 3 was designated as the bi-directional data port, and the lower nibble of port 4 was reserved as control lines. While the serial port could have been used to achieve bidirectional connectivity with the host PC, higher data transfer rates were desired to allow for more waveforms to be transferred per second in the intended TDR instrument application.
Host PC Overview
The PC parallel port operating in standard mode (SPP) was used. The parallel port consists of three registers/ports. The 8-bit data port was originally designed by IBM as output only, but nearly all relatively recent implementations allow the data port to operate in both directions. The lower nibble of the control port can also be used as input or output, and the upper five bits of the status port are permanently configured as inputs. Some of the bits in the control and status ports are inverted at the connector, requiring appropriate adjustments in the software to achieve the desired behavior. The upper nibble of the control port is reserved. However, writing a 1 to C5 changes the data port to high impedance state, thereby allowing the port to read the value placed on the pins. It was determined experimentally that the port in the computer used had 2.2k internal pullup resistors. The pulled up voltage on the data and status ports was measured to be approximately 4.3V. A diagram of the parallel port connecter is shown below in Figure 1.
Figure 1.
Interface Resource Allocation
The communication schematic is shown below in Figure 2.
Figure 2. Resource Allocation
The 8-bit wide bi-directional data port sends or receives data. The request (RQ) line is used to initiate a transaction with the microcontroller, and the clock (CLK) line is used to synchronize each byte as it is transferred. The ready (RDY) and acknowledge (ACK) lines provide status indicators as to the state of the current transaction.
Protocol Definition
The PC host interface is defined as the master, and the ADuC7026 as the slave. The master initiates all data transfers, and controls the transfer sequence with the clock signal. In the current implementation, the transfer length is fixed in the code and must be the same on both the master and slave. The basic protocol outlined below can easily be upgraded later to allow for variable length transfers. The direction of the transfer is specified by the state of the CK line at the time that the request (RQ) line is raised to initiate a transfer. If the CK=1, the transfer is from the device to the host, otherwise from the host to the device. The basic transfer protocol is outlined in detail below.
Host-to-Device
Transfer
Device-to-Host
Transfer
Due to the full software handshaking in place, the protocol as outlined is not time sensitive. However, to prevent either the host or device from locking up in the case of excessively long response times (or no response/error), iteration limitations are used in the wait cycles to impose a timeout on the transfer sequence. In this way the robustness of the protocol is ensured. No error checking provisions are made in the basic transfer sequence. For most applications, this is probably acceptable due to the rarity of bit errors, especially considering that the data being transferred in the intended target application is relatively non-critical.
The protocol from the device perspective is analogous to the host side, and can be readily arrived at by considering what sequence is required by the host for a successful data transfer.
Software
The PC host software was implemented using the DriverLinx DlPortIO generic port driver for Windows 2000/XP. The driver is freely downloadable from the http://www.driverlinx.com website, and provides direct port access under the aforementioned protected-mode operating systems. A graphical user interface application was written in C++ using the wxWidgets 2.6 (http://www.wxwidgets.org) toolkit to facilitate easy testing of the communication interface. The application consists of a scrolled text window in which status messages and output are displayed, as well as a command entry widget into which commands can be typed and executed by pressing Enter. The currently available commands in the Commhost application are listed below. An application screen shot is included below.
Figure 3. Commhost Test Application Screenshot.
The ADuC7026 software is programmed in C and is compiled with the Keil uVision 3 development studio using the GCC-ARM7 compiler. These tools were provided on the development kit CDROM.
The code is set up to transfer a 9-byte buffer between the two devices. The buffer and its length are of course passed as parameters to the read/write functions, so any length data transfer can be achieved. Higher levels of abstraction may provide the necessary sequencing of low-level read/write functions to achieve variable length data transfers between the host and target device.
Hardware Connector
An adaptor was built to connect the DB-25 parallel port cable to the ADuC7026 development board, and to facilitate easy debugging. The adaptor is shown in Figure 4.
Figure 4. DB-25 to Development Board Adaptor
Series 180 ohm resistors were placed between the parallel port and the ADI chip to help protect the microcontroller and parallel port from high currents in the event that outputs on both sides were enabled at the same time. The resistors were used on the control port and the data port, but not on the status port since it cannot ever be driven by the parallel port. The resistor leads on the top side were left longer to allow oscilloscope probes to be attached with ease for debugging purposes.
Testing
After some debugging, both the read and write sequences worked correctly. Correct operation of the bidirectional transfer was readily verified using the Commhost interface application, and further documented using a Tektronix oscilloscope. The following scope screens show the read and write transfers.
Figure 5. 9-byte Read Operation (Device to Host)
Figure 6. 9-byte Write Operation (Host to Device)
Using the oscilloscope cursors, the data transfer rate is readily determined.
This is a reasonably fast transfer rate of about 0.5 MBit/sec, considering that the all of the synchronization is done in software. It is indeed much faster than RS-232 for bulk data transfer.
Conclusions
The simple parallel port communication interface provides a straightforward mechanism for interacting with the ADuC7026 microcontroller with reasonably high speed bulk data transfer capabilities. Using the low level read/write commands outlined in this document, higher level protocols can be easily designed with the intended target application in mind.
While the resistive current limiting is sufficient for laboratory testing and product development, a finished product should use bidirectional buffers between the ADI chip and the parallel port to fully protect the microcontroller from erroneous parallel port conditions, even though the device claims to be 5-V logic tolerant.
Appendix A ADuC7026
Microcontroller Code
comm.c
#include <aduc7026.h>
/*
Parallel
port ADuC7026
D0 .. D7
<------> P3.0 .. P3.7
S4
<--RDY-- P4.0
S5 <--ACK-- P4.1
C0
---CK--> P4.2 (also DIR during request)
C2
---RQ--> P4.3
C1 -INTR--> P0.4
*/
typedef unsigned char UINT8;
typedef unsigned long UINT32;
#define INPUT 0
#define OUTPUT 1
/* ADuC7026 port GPxDAT register
bits
31-24
direction of data ('1':output, '0':input)
23-16 port
x data output
15-8
reflect state of port x pins at reset (read only)
7-0 port
x data input (read only)
*/
// communication config/read/write macros
#define SET_DATA_INPUT (GP3DAT &= 0x00ffffff)
#define SET_DATA_OUTPUT (GP3DAT |= 0xff000000)
#define WRITE_DATA(val)
(GP3DAT = (GP3DAT & ~0x00ff0000) | (((UINT32)val) << 16)) // write port 3 data
#define READ_DATA ((UINT8)(GP3DAT
& 0x000000ff)) // read port 3 data
#define READ_CK ((UINT8)((GP4DAT
& 0x00000004)>>2)) // pin 4.2
#define READ_RQ ((UINT8)((GP4DAT &
0x00000008)>>3)) // pin 4.3
#define READ_INTR ((UINT8)((GP0DAT &
0x00000010)>>4)) // pin 0.4
(xirq0)
#define WRITE_ACK(val)
(GP4DAT = (GP4DAT & ~0x00020000) | (((UINT32)val)<<17)) // pin 4.1
#define WRITE_RDY(val)
(GP4DAT = (GP4DAT & ~0x00010000) | (((UINT32)val)<<16)) // pin 4.0
#define COMM_READ 0
#define COMM_WRITE 1
enum { S_IDLE, S_READ_REQUEST,
S_WRITE_REQUEST, S_TRANSFERRING };
static int cur_state = S_IDLE;
static int comm_attempts = 1000000;
int comm_read(UINT8 *buf, int count)
{
int i, timeout;
cur_state
= S_TRANSFERRING;
// set
port direction as input
SET_DATA_INPUT;
//
assert ready signal
WRITE_RDY(1);
/* wait
for request line to go low again */
while ( READ_RQ );
for (i=0;i<count;i++)
{
//
wait for clock to go high
timeout = comm_attempts;
while(timeout>0 && !READ_CK)
timeout--;
if (!timeout)
{
WRITE_RDY(0);
cur_state
= S_IDLE;
return -1;
}
//
now the data is available, so read it
buf[i] = READ_DATA;
//
assert ACK to indicate data was read
WRITE_ACK(1);
//
wait for clock to go low
timeout = comm_attempts;
while(timeout>0 && READ_CK)
timeout--;
if (!timeout)
{
WRITE_RDY(0);
cur_state
= S_IDLE;
return -1;
}
//
lower ACK to indicate byte transfer complete
WRITE_ACK(0);
}
// pull
ready line low
WRITE_RDY(0);
cur_state
= S_IDLE; // revert to IDLE state
return i; // return number of bytes read
}
int comm_write(UINT8 *buf, int count)
{
int i, timeout;
cur_state
= S_TRANSFERRING;
// set
port direction as output
SET_DATA_OUTPUT;
//
assert ready signal
WRITE_RDY(1);
/* wait
for request line (XIRQ0) to go low again */
while (READ_RQ);
for(i=0;i<count;i++)
{
//
wait for the clock to go low
timeout = comm_attempts;
while(timeout>0 && READ_CK)
timeout--;
if (!timeout)
{
WRITE_RDY(0);
cur_state
= S_IDLE;
return -1;
}
//
place data on outputs
WRITE_DATA( buf[i] );
//
assert ACK to indicate data is available
WRITE_ACK(1);
//
wait for clock to go high again
timeout = comm_attempts;
while(timeout>0 && !READ_CK)
timeout--;
if (!timeout)
{
WRITE_RDY(0);
cur_state
= S_IDLE;
return -1;
}
//
pull ACK low to indicate byte transfer complete
WRITE_ACK(0);
}
// pull
ready signal low
WRITE_RDY(0);
cur_state
= S_IDLE; // revert to IDLE state
return i; // return number of bytes written
}
void setup_comm()
{
//
configure ports 3 and 4 as GPIO
GP3CON =
0x00000000;
GP4CON =
0x00000000;
// set
pin 4.1, 4.0 as output
// set
pin 4.2, 4.3 as input
GP4DAT =
0x03000000;
// set
port 0 as input
GP0DAT =
0x00000000;
// start
with port 3 as input
SET_DATA_INPUT;
}
int main()
{
//
configure gpio ports
setup_comm();
#define BUFLEN 9
static unsigned char databuf[BUFLEN] = { 254, 128, 64, 32,
16, 8, 4, 2, 0 };
while(1)
{
//
wait for a communication request
while (!READ_RQ);
//
determine direction of data transfer
if ( READ_CK )
comm_write(databuf, BUFLEN);
else
comm_read(databuf, BUFLEN);
}
return 0;
}
/**************************************
** single byte read/write commands **
**************************************/
UINT8 readbyte()
{
UINT8 val = 0;
SET_DATA_INPUT;
/* wait
for request */
while(!READ_RQ);
val = READ_DATA;
WRITE_ACK(1);
while(READ_RQ);
WRITE_ACK(0);
return val;
}
void writebyte(UINT8 val)
{
while(!READ_RQ);
SET_DATA_OUTPUT;
WRITE_DATA(val);
WRITE_ACK(1);
while(READ_RQ);
SET_DATA_INPUT;
WRITE_ACK(0);
}
void test_main()
{
UINT8 x
= 0;
GP3CON =
0x00000000;
GP4CON =
0x00000000;
GP4DAT =
0x03000000;
GP0DAT =
0x00000000;
SET_DATA_INPUT;
WRITE_RDY(0);
WRITE_ACK(0);
while(1)
{
x
= readbyte();
writebyte(x+1);
}
}
Appendix B PC Commhost Source Code
commadi.h
#ifndef __commadi_h__
#define __commadi_h__
typedef void
(*comm_print_func)(const char*, void*);
void comm_set_print( comm_print_func
f, void *cbdata);
void comm_set_timeout(int
attempts);
void comm_test_bidir();
void comm_test_ports();
int comm_read_stat();
void comm_clear();
/* these functions return
the number of bytes
written or read
or
-1 for to indicate an error
*/
int comm_write( unsigned char *buf, int count);
int comm_read( unsigned char *buf, int count);
#endif
commadi.cpp
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<windows.h>
#include
"dlportio.h"
#include
"commadi.h"
//
unsigned char x = DlPortReadPortUchar(PP_STAT);
// DlPortWritePortUchar(PP_DATA, 33);
typedef
unsigned char UINT8;
#define
PP_STAT 0x379
#define
PP_CNTL 0x37A
#define
PP_DATA 0x378
static
UINT8 ppdata_val = 0;
static
UINT8 ppcntl_val = 0;
/*
Parallel port ADuC7026
D0 .. D7 <------> P3.0 .. P3.7
S4
<--RDY-- P4.0
S5
<--ACK-- P4.1
C0
---CK--> P4.2 (also DIR during request)
C2
---RQ--> P4.3
C1 -INTR--> P0.4
*/
#define
RQ_BIT 2
#define
INTR_BIT 1
#define
CK_BIT 0
#define
RDY_BIT 4
#define
ACK_BIT 5
/* xor
the status and control ports with the appropriate masks
to take care of the
inverted signals on specific pins */
#define
READSTAT ((UINT8)(DlPortReadPortUchar(PP_STAT)
^ 0x80))
#define
READDATA ((UINT8)DlPortReadPortUchar(PP_DATA))
#define
READCNTL ((UINT8)DlPortReadPortUchar(PP_CNTL)^0x0b)
#define
WRITEDATA DlPortWritePortUchar( PP_DATA,
(UINT8)ppdata_val )
#define
WRITECNTL DlPortWritePortUchar( PP_CNTL,
(UINT8)((ppcntl_val ^ 0x0b)&0x3F) )
#define
WRITE_RQ(x) changebit(&ppcntl_val, RQ_BIT, x);
WRITECNTL
#define
WRITE_CK(x) changebit(&ppcntl_val, CK_BIT, x);
WRITECNTL
#define
WRITE_INTR(x) changebit(&ppcntl_val, INTR_BIT, x);
WRITECNTL
#define
INPUT 0
#define
OUTPUT 1
static
comm_print_func print_func = NULL;
static
void *print_cbdata = NULL;
static
int commattempts = 1000000;
void comm_set_timeout(int
attempts)
{
commattempts =
attempts;
}
void
comm_set_print( comm_print_func f, void *cbdata)
{
print_func = f;
print_cbdata = cbdata;
}
static
void commprint(const char *fmt, ...)
{
static char
buf[1024];
if (print_func !=
NULL)
{
va_list
args;
va_start(args,
fmt);
_vsnprintf(buf,
1024, fmt, args);
va_end(args);
(*print_func)(buf,
print_cbdata);
}
}
static
void changebit( UINT8 *data, UINT8 pos, UINT8 value)
{
if (!data)
return;
if (value)
{
*data |= (0x1 << pos);
}
else
{
UINT8 mask = (UINT8) ~(0x01 << pos);
*data &= mask;
}
}
static
void set_data_dir(int dir)
{
if (dir == INPUT)
changebit(&ppcntl_val,
5, 1);
else
changebit(&ppcntl_val,
5, 0);
commprint("set
data dir: '%s' (CNTL=0x%x). ",
dir==INPUT?"input":"output", ppcntl_val);
WRITECNTL;
commprint("[read
cntl=0x%x]\n", READCNTL&0x3F);
}
inline
void writebyte(UINT8 x)
{
int timeout;
/* apply the data */
set_data_dir(OUTPUT);
ppdata_val = x;
WRITEDATA;
/* indicate write operation */
WRITE_CK(0);
/* assert request */
WRITE_RQ(1);
/* wait for ACK signal to go high*/
timeout =
commattempts;
while(timeout--
> 0 && !(READSTAT & 0x20));
/* deassert RQ */
WRITE_RQ(0);
/* wait for ACK signal to go low */
timeout =
commattempts;
while(timeout--
> 0 && (READSTAT & 0x20));
set_data_dir(INPUT);
}
inline
UINT8 readbyte()
{
UINT8 val;
int timeout;
set_data_dir(INPUT);
/* assert request */
WRITE_RQ(1);
/* wait for ACK signal to go high*/
timeout=commattempts;
while(timeout--
> 0 && !(READSTAT & 0x20));
/* read the data */
val = READDATA;
commprint("readdata=%d\n",
READDATA);
/* deassert RQ */
WRITE_RQ(0);
/* wait for ACK signal to go low */
timeout =
commattempts;
while(timeout--
> 0 && (READSTAT & 0x20));
return val;
}
void
comm_test_ports()
{
int timeout = 0;
UINT8 x = 0;
writebyte(35);
x = readbyte();
commprint("comm
port test sequence completed [wrote 35, read %d]\n", x);
}
void
comm_test_bidir()
{
int i;
UINT8 x;
set_data_dir(OUTPUT);
ppdata_val = 1;
WRITEDATA;
ppdata_val = 0;
WRITEDATA;
commprint("testing
bidir...\n");
for
(i=0;i<10;i++)
{
ppdata_val = 100-i;
WRITEDATA;
x = READDATA;
commprint("\tread(mode:out):
0x%x\n", x);
}
set_data_dir(INPUT);
for
(i=0;i<10;i++)
{
ppdata_val++;
WRITEDATA;
x = READDATA;
commprint("\tread(mode:in):
0x%x\n", x);
}
ppdata_val = 0;
WRITEDATA;
}
void
comm_write0()
{
ppdata_val = 0;
ppcntl_val = 0;
WRITEDATA;
WRITECNTL;
set_data_dir(INPUT);
}
int
comm_write( unsigned char *buf, int count)
{
int i;
int timeout = 0;
/* start with port as input for safety */
set_data_dir(OUTPUT);
/* set CK/DIR to 0 to indicate write
operation */
WRITE_CK(0);
/* raise request line */
WRITE_RQ(1);
/* wait for RDY to go high */
timeout =
commattempts;
while(timeout
> 0 && !(READSTAT & 0x10))
timeout--;
/* if we got no response, return error */
if (!timeout)
{
commprint("WRITE
timed out waiting for RDY to go high ('1')\n");
return -1;
}
/* pull request line low again */
WRITE_RQ(0);
for
(i=0;i<count;i++)
{
/* write the byte to the data port
*/
ppdata_val = buf[i];
WRITEDATA;
/* raise the clock */
WRITE_CK(1);
/* wait for the ACK signal to go
high,
indicating that the byte was read */
timeout =
commattempts;
while(timeout
> 0 && !(READSTAT & 0x20))
timeout--;
if
(!timeout)
{
commprint("write
timed out waiting for ACK to go high ('1')\n");
WRITE_CK(0);
WRITE_RQ(0);
set_data_dir(INPUT);
return
-1;
}
/* lower the clock */
WRITE_CK(0);
/* wait for the ACK signal to go
low,
indicating that the transaction was done */
timeout =
commattempts;
while(timeout
> 0 && (READSTAT & 0x20))
timeout--;
if
(!timeout)
{
commprint("write
timed out waiting for ACK to go low ('0') again\n");
WRITE_CK(0);
WRITE_RQ(0);
set_data_dir(INPUT);
return
-1;
}
}
/* change back to input mode */
set_data_dir(INPUT);
return i;
}
int
comm_read( unsigned char *buf, int count)
{
int i;
int timeout = 0;
set_data_dir(INPUT);
/* set CK/DIR to 1 to indicate read
operation */
WRITE_CK(1);
/* raise request line */
WRITE_RQ(1);
/* wait for RDY to go high */
timeout =
commattempts;
while(timeout
> 0 && !(READSTAT & 0x10))
timeout--;
/* if we got no response, return error */
if (!timeout)
{
WRITE_CK(0);
WRITE_RQ(0);
commprint("READ
timed out waiting for RDY to go high ('1')\n");
return -1;
}
/* lower request line again */
WRITE_RQ(0);
for
(i=0;i<count;i++)
{
/* lower the clock */
WRITE_CK(0);
/* wait for the ACK signal to go
high
indicating that the data is ready */
timeout =
commattempts;
while(timeout
> 0 && !(READSTAT & 0x20))
timeout--;
if
(!timeout)
{
WRITE_CK(0);
WRITE_RQ(0);
commprint("READ
timed out waiting for ACK to go high ('1')\n");
return
-1;
}
/* read the byte from the data port
*/
buf[i] =
READDATA;
/* raise the clock */
WRITE_CK(1);
/* wait for the ACK signal to go low
indicating that the transaction was done */
timeout =
commattempts;
while(timeout
> 0 && (READSTAT & 0x20))
timeout--;
if
(!timeout)
{
WRITE_CK(0);
WRITE_RQ(0);
commprint("READ
timed out waiting for ACK to go low ('0') again\n");
return
-1;
}
}
WRITE_CK(0);
WRITE_RQ(0);
return i;
}
int
comm_read_stat()
{
UINT8 val = READSTAT;
commprint("comm_read_stat:
0x%x\n", val);
return (int)val;
}
afwx.h
#ifndef
AFWX_H
#define
AFWX_H
extern
wxConfig *app_config;
class
AFApp : public wxApp
{
public:
AFApp();
bool OnInit();
int OnExit();
};
DECLARE_APP(AFApp)
#define
MAX_RECENT 9
class
AFView;
class
AFHelp;
class
AFFrame : public wxFrame
{
public:
AFFrame();
virtual
~AFFrame();
void New();
void Load(const
wxString &fn);
void Open();
void Save();
void SaveAs();
bool
CloseDocument();
void ShowHelp();
void Exit();
void
UpdateControlStatus();
void
UpdateTitlebar();
void Append(const
wxString &str);
private:
void
OnInput(wxCommandEvent &evt);
void
OnDocumentCommand(wxCommandEvent &evt);
void
OnEditCommand(wxCommandEvent &evt);
void
OnUpdateEditMenuUI(wxUpdateUIEvent &evt);
void
OnPrintCommand(wxCommandEvent &evt);
void
OnRecent(wxCommandEvent &evt);
void
OnExit(wxCommandEvent &evt);
void
OnAbout(wxCommandEvent &evt);
void
OnHelp(wxCommandEvent &evt);
void
AddRecent(const wxString &fn);
void RemoveRecent(const
wxString &fn);
void
UpdateRecentMenu();
void
OnCloseFrame(wxCloseEvent &evt);
wxMenu
*mFileMenu, *mRecentMenu;
wxToolBar
*mToolBar;
wxString
mFilename;
wxTextCtrl
*mOutput, *mInput;
AFHelp *mHelpView;
int mRecentCount;
wxString
mRecentFiles[MAX_RECENT];
DECLARE_EVENT_TABLE()
};
#endif
afwx.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wx/wx.h>
#include <wx/scrolbar.h>
#include <wx/print.h>
#include <wx/printdlg.h>
#include <wx/accel.h>
#include <wx/image.h>
#include <wx/fs_zip.h>
#include <wx/html/htmlwin.h>
#include <wx/config.h>
#include "painter.h"
#include "afhelp.h"
#include "afwx.h"
#include "commadi.h"
#include "stock_new.xpm"
#include "stock_open.xpm"
#include "stock_save.xpm"
#include "stock_save_as.xpm"
#include "stock_trash_full.xpm"
#include "stock_print.xpm"
#include "stock_convert.xpm"
#include "stock_undo.xpm"
#include "stock_redo.xpm"
#include "stock_button_cancel.xpm"
#include "stock_zoom_in.xpm"
#include "stock_zoom_out.xpm"
#include "stock_zoom_fit.xpm"
#include "stock_jump_to.xpm"
#include "stock_refresh.xpm"
#include "stock_index.xpm"
#include "stock_help.xpm"
#include "aficon.xpm"
/* application global variables */
static AFFrame *app_frame = NULL;
static wxArrayString app_args;
wxConfig *app_config = NULL;
/* AFFrame implementation */
IMPLEMENT_APP(AFApp)
AFApp::AFApp()
{
/* nothing to do
*/
}
bool AFApp::OnInit()
{
for (int i=0;i<argc;i++)
app_args.Add(argv[i]);
#ifdef MESSAGES
printf("AF-WX Application Framework (WX): Starting
up...\n");
printf("Framework by Aron Dobos\n");
printf("Command line args: %d\n",
app_args.Count());
for (int k=0;k<app_args.Count();k++)
printf("argv[%d]: '%s'\n", k,
app_args[k].c_str());
#endif
app_config = new wxConfig("Commhost", "AF_Applications");
/* needed for the
html help viewer */
wxImage::AddHandler(new wxPNGHandler);
wxImage::AddHandler(new wxJPEGHandler);
wxFileSystem::AddHandler(new wxZipFSHandler);
app_frame = new
AFFrame;
app_frame->Centre(wxBOTH);
app_frame->Show(true);
SetTopWindow(app_frame);
if ((int)app_args.Count() > 1)
app_frame->Load(app_args[1]);
return true;
}
int AFApp::OnExit()
{
// delete the app
config
// (it
automatically writes the configuration)
delete app_config;
#ifdef MESSAGES
printf("AF-WX: Shutdown complete.\n");
#endif
return 0;
}
enum{
ID_NEW,
ID_OPEN, ID_SAVE, ID_SAVEAS, ID_CLOSEFILE,
ID_RECENT_FILES,
ID_EXIT,
ID_ABOUT,
ID_HELP,
ID_OUTPUT,
ID_INPUT,
// up to
100 recent items can be accommodated
ID_RECENT =
500,
ID_RECENT_LAST
= 600,
};
BEGIN_EVENT_TABLE(AFFrame, wxFrame)
EVT_MENU( ID_NEW, AFFrame::OnDocumentCommand
)
EVT_MENU( ID_OPEN, AFFrame::OnDocumentCommand )
EVT_MENU( ID_SAVE, AFFrame::OnDocumentCommand )
EVT_MENU( ID_SAVEAS, AFFrame::OnDocumentCommand )
EVT_MENU( ID_CLOSEFILE, AFFrame::OnDocumentCommand )
EVT_MENU( ID_EXIT, AFFrame::OnExit )
EVT_MENU( ID_ABOUT, AFFrame::OnAbout )
EVT_MENU( ID_HELP, AFFrame::OnHelp )
EVT_TEXT_ENTER( ID_INPUT, AFFrame::OnInput)
EVT_CLOSE( AFFrame::OnCloseFrame )
// For recent file menu
EVT_MENU( ID_RECENT+0, AFFrame::OnRecent)
EVT_MENU( ID_RECENT+1, AFFrame::OnRecent)
EVT_MENU( ID_RECENT+2, AFFrame::OnRecent)
EVT_MENU( ID_RECENT+3, AFFrame::OnRecent)
EVT_MENU( ID_RECENT+4, AFFrame::OnRecent)
EVT_MENU( ID_RECENT+5, AFFrame::OnRecent)
EVT_MENU( ID_RECENT+6, AFFrame::OnRecent)
EVT_MENU( ID_RECENT+7, AFFrame::OnRecent)
EVT_MENU( ID_RECENT+8, AFFrame::OnRecent)
EVT_MENU( ID_RECENT+9, AFFrame::OnRecent) // this must go all
the way to MAX_RECENT-1
END_EVENT_TABLE()
void afprint_output(const char *str, void
*data)
{
((AFFrame*)data)->Append( str );
}
AFFrame::AFFrame()
: wxFrame(NULL, -1, "Commhost", wxDefaultPosition,
wxSize(700, 600))
{
mFilename = "";
mRecentCount = 0;
CreateStatusBar(1);
wxString helpfile = wxPathOnly(app_args[0]) +
"/commhosthelp.zip#zip:index.html";
mHelpView = new AFHelp(helpfile);
#ifdef __WXMSW__
SetIcon( wxIcon("aficon") );
#else
SetIcon( wxIcon( aicon_xpm ) );
#endif
mRecentMenu = new wxMenu;
mFileMenu = new wxMenu;
/* mFileMenu->Append(ID_NEW, "New\tCtrl-N");
mFileMenu->AppendSeparator();
mFileMenu->Append(ID_OPEN, "Open...\tCtrl-O");
mFileMenu->Append(ID_SAVE, "Save\tCtrl-S");
mFileMenu->Append(ID_SAVEAS, "Save As...");
mFileMenu->AppendSeparator();
mFileMenu->Append(ID_CLOSEFILE, "Close");
mFileMenu->AppendSeparator();
mFileMenu->Append(ID_RECENT_FILES, "Recent
Files", mRecentMenu);
mFileMenu->AppendSeparator();*/
mFileMenu->Append(ID_EXIT, "Exit\tCtrl-W");
wxMenu *help_menu = new wxMenu;
help_menu->Append(ID_ABOUT, "About Commhost");
help_menu->AppendSeparator();
help_menu->Append(ID_HELP, "Help Contents\tF1");
wxMenuBar *menubar = new wxMenuBar;
menubar->Append(mFileMenu, "File");
menubar->Append(help_menu, "Help");
SetMenuBar( menubar );
/* mToolBar = CreateToolBar();
mToolBar->AddTool( ID_NEW, wxBitmap( stock_new_xpm ),
"Create a new document" );
mToolBar->AddTool( ID_OPEN, wxBitmap( stock_open_xpm ),
"Open an existing file" );
mToolBar->AddTool( ID_SAVE, wxBitmap( stock_save_xpm ),
"Save changes");
mToolBar->AddTool( ID_SAVEAS, wxBitmap( stock_save_as_xpm
), "Save to a different file" );
mToolBar->AddTool( ID_HELP, wxBitmap( stock_help_xpm ),
"Help contents" );
mToolBar->SetToolBitmapSize(wxSize(24,
24));
mToolBar->Realize();*/
wxFont font(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL,
wxFONTWEIGHT_NORMAL,
false, "courier");
mOutput = new wxTextCtrl(this, ID_OUTPUT, "",
wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE
| wxTE_DONTWRAP | wxHSCROLL | wxVSCROLL);
mOutput->SetFont(font);
mOutput->SetEditable(false);
comm_set_print( afprint_output, this );
mInput = new wxTextCtrl(this, ID_INPUT, "",
wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER);
mInput->SetFont(font);
wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
SetSizer(sizer);
sizer->Add(mOutput, 1, wxEXPAND);
sizer->Add(mInput, 0, wxEXPAND);
sizer->Fit(this);
sizer->SetSizeHints(this);
SetSize(500, 500);
mInput->SetFocus();
long ct = 0;
if (app_config->Read("RecentCount", &ct))
mRecentCount = (int)ct;
if (mRecentCount > MAX_RECENT)
mRecentCount = MAX_RECENT;
for (int i=0;i<mRecentCount;i++)
{
wxString key;
key.Printf("RecentFile_%d", i);
wxString fn;
if (app_config->Read(key, &fn))
mRecentFiles[i] = fn;
}
UpdateRecentMenu();
UpdateControlStatus();
UpdateTitlebar();
New();
/* clear the
output port */
comm_clear();
}
AFFrame::~AFFrame()
{
// save the
recent file settings
long ct = (long)mRecentCount;
app_config->Write("RecentCount", ct);
for (int i=0;i<mRecentCount;i++)
{
wxString key;
key.Printf("RecentFile_%d", i);
app_config->Write(key, mRecentFiles[i]);
}
mHelpView->Destroy();
#ifdef MESSSAGES
printf("~AFFrame: destructing the main
window...\n");
#endif
}
void AFFrame::Append(const wxString
&str)
{
mOutput->AppendText(str);
}
void AFFrame::OnInput(wxCommandEvent
&evt)
{
#define BUFLEN 9
static unsigned char databuf[BUFLEN] = { 0, 2, 4, 8, 16, 32,
64, 128, 255 };
wxString cmd = mInput->GetValue();
if (cmd == "")
return;
mOutput->AppendText(">> " + cmd +
"\n");
mInput->SetValue("");
cmd.Lower();
if (cmd == "bidir")
{
comm_test_bidir();
}
else if (cmd == "disp")
{
Append(wxString::Format("Data buffer (len:%d)\n",
BUFLEN));
for (int i=0;i<BUFLEN;i++)
Append( wxString::Format(">> %d: '%d'\n", i,
databuf[i]));
}
else if (cmd == "w")
{
comm_read_stat();
int ret = comm_write(databuf, BUFLEN);
if (ret > 0)
{
for (int i=0;i<BUFLEN;i++)
Append( wxString::Format("%d: '%d'\n", i,
databuf[i]));
Append("write succeeded.\n");
}
else
Append("write failed.\n");
}
else if (cmd == "inc")
{
for (int i=0;i<BUFLEN;i++)
databuf[i]++;
}
else if (cmd == "r")
{
comm_read_stat();
int ret = comm_read(databuf, BUFLEN);
if (ret > 0)
{
Append("read succeeded.\n");
for (int i=0;i<BUFLEN;i++)
Append( wxString::Format("%d: '%d'\n", i, databuf[i]));
}
else
Append("read failed.\n");
}
else if (cmd == "t")
{
comm_test_ports();
}
else
{
mOutput->AppendText("unknown command!\n");
}
}
void AFFrame::UpdateRecentMenu()
{
int i;
for (i=0;i<MAX_RECENT;i++)
{
if (mRecentMenu->FindItem(ID_RECENT+i) != NULL)
mRecentMenu->Destroy(ID_RECENT+i);
}
for (i=0;i<mRecentCount;i++)
{
wxString name;
name.Printf("%d
%s", i+1, mRecentFiles[i].c_str());
mRecentMenu->Append(ID_RECENT+i, name);
}
}
void AFFrame::OnRecent(wxCommandEvent
&evt)
{
int id = evt.GetId() - ID_RECENT;
if (id < 0 || id >= MAX_RECENT)
return;
if (!CloseDocument())
return;
wxString fn = mRecentFiles[id];
if (fn != "")
{
//wxMessageBox("loading recent file " + fn);
Load(fn);
}
}
void AFFrame::AddRecent(const wxString
&fn)
{
int i;
int index = -1;
// find the file
in the recent list
for (i=0;i<mRecentCount;i++)
{
if (fn == mRecentFiles[i])
{
index = i;
break;
}
}
if (index >= 0)
{
// bring
this file to the front of the
// recent
file list
for (i=index;i>0;i--)
mRecentFiles[i] = mRecentFiles[i-1];
}
else // not found in recent list
{
// add this
to the front of the recent list
// and
increment the recent count if its
// less
than MAX_RECENT
for (i=MAX_RECENT-1;i>0;i--)
mRecentFiles[i] = mRecentFiles[i-1];
if (mRecentCount < MAX_RECENT)
mRecentCount++;
}
mRecentFiles[0] = fn;
UpdateRecentMenu();
}
void AFFrame::RemoveRecent(const wxString
&fn)
{
int i;
int index = -1;
// find the file
in the recent list
for (i=0;i<mRecentCount;i++)
{
if (fn == mRecentFiles[i])
{
index = i;
break;
}
}
if (index >= 0)
{
for (i=index;i<MAX_RECENT-1;i++)
mRecentFiles[i] = mRecentFiles[i+1];
mRecentCount--;
UpdateRecentMenu();
}
}
void AFFrame::ShowHelp()
{
mHelpView->Show();
}
void AFFrame::OnCloseFrame( wxCloseEvent
&evt )
{
if (evt.CanVeto() && (!CloseDocument()))
{
evt.Veto();
return;
}
Destroy();
}
void AFFrame::New()
{
if (!CloseDocument())
return;
// INITIALIZE NEW
DOCUMENT HERE
UpdateTitlebar();
UpdateControlStatus();
}
void AFFrame::Load(const wxString &fn)
{
mFilename = fn;
// READ DATA HERE
UpdateTitlebar();
UpdateControlStatus();
}
void AFFrame::Open()
{
if (!CloseDocument())
return;
wxString initial_dir = "";
wxFileDialog fdlg(this, "Open File", initial_dir,
"", "All Files(*.*)", wxOPEN);
if (fdlg.ShowModal() == wxID_OK)
Load( fdlg.GetPath() );
}
void AFFrame::Save()
{
if (mFilename == "")
{
SaveAs();
return;
}
// WRITE DATA
HERE
UpdateTitlebar();
UpdateControlStatus();
}
void AFFrame::SaveAs()
{
wxString caption;
caption.Printf("Save As: '%s'", mFilename !=
"" ? mFilename.c_str() :
"untitled");
wxString initial_dir = "";
if ( mFilename != "" )
initial_dir
= wxPathOnly( mFilename );
wxString FileName;
wxFileName::SplitPath(mFilename, NULL, &FileName, NULL);
wxFileDialog fdlg(this, caption, initial_dir, FileName + ".lay",
"All
Files (*.*)", wxSAVE | wxOVERWRITE_PROMPT );
if (fdlg.ShowModal() == wxID_OK)
{
if (fdlg.GetPath() != "")
{
mFilename = fdlg.GetPath();
Save();
return;
}
else
{
wxMessageBox("No filename selected", "",
wxOK | wxICON_ERROR);
}
}
}
bool AFFrame::CloseDocument()
{
if ( /* CHECK IF SOMETHING IS MODIFIED */ false )
{
int ret = wxMessageBox("Document has been modified.
Save it?", "AFedit", wxYES_NO | wxCANCEL | wxICON_EXCLAMATION);
if (ret == wxYES)
{
Save();
if ( false /* CHECK AGAIN IF STILL MODIFIED */)
return false;
}
else if (ret == wxCANCEL)
{
return false;
}
}
/* UNLOAD
DOCUMENT AND DATA */
mFilename = "";
UpdateTitlebar();
UpdateControlStatus();
return true;
}
void AFFrame::Exit()
{
Close( false );
}
void
AFFrame::OnDocumentCommand(wxCommandEvent &evt)
{
switch(evt.GetId())
{
case ID_NEW:
New();
break;
case ID_OPEN:
Open();
break;
case ID_SAVE:
Save();
break;
case ID_SAVEAS:
SaveAs();
break;
case ID_CLOSEFILE:
CloseDocument();
default:
break;
}
}
void AFFrame::OnExit(wxCommandEvent
&evt)
{
Exit();
}
void AFFrame::OnAbout(wxCommandEvent
&evt)
{
wxString msg;
msg.Printf("Commhost\n"
"
"Copyright
(c) 2005 Aron Dobos\n");
wxMessageBox(msg,"About Commhost", wxOK |
wxICON_INFORMATION);
}
void AFFrame::OnHelp(wxCommandEvent
&evt)
{
mHelpView->Show();
}
void AFFrame::UpdateControlStatus()
{
bool DocumentPresent = false;
bool DocumentDirty = false;
/*
mFileMenu->Enable(ID_SAVE, DocumentPresent &&
DocumentDirty);
mFileMenu->Enable(ID_SAVEAS, DocumentPresent);
mFileMenu->Enable(ID_CLOSEFILE, DocumentPresent);
mFileMenu->Enable(ID_RECENT_FILES, mRecentCount > 0 );
mToolBar->EnableTool(ID_NEW,
mFileMenu->IsEnabled(ID_NEW));
mToolBar->EnableTool(ID_OPEN, mFileMenu->IsEnabled(ID_OPEN));
mToolBar->EnableTool(ID_SAVE,
mFileMenu->IsEnabled(ID_SAVE));
mToolBar->EnableTool(ID_SAVEAS,
mFileMenu->IsEnabled(ID_SAVEAS));
*/
}
void AFFrame::UpdateTitlebar()
{
bool dirty = false; /* CHECK IF DATA IS MODIFIED */
wxString title;
title.Printf("%s%s - Commhost", mFilename.length()
> 0 ? wxFileNameFromPath(mFilename).c_str() : "Untitled", dirty ?
"*":"");
SetTitle( title );
}
afhelp.h
#ifndef __afhelp_h
#define __afhelp_h
#include <wx/html/htmlwin.h>
class AFHelp : public wxFrame
{
public:
AFHelp(const wxString &zipfile);
virtual ~AFHelp();
void OnCloseFrame(wxCloseEvent &evt);
void OnTool(wxCommandEvent &evt);
private:
wxToolBar *mToolBar;
wxHtmlWindow *mHtml;
wxString mZipFilePath;
DECLARE_EVENT_TABLE();
};
#endif
afhelp.cpp
#include <wx/wx.h>
#include <wx/html/htmlwin.h>
#include "afhelp.h"
#include "stock_close.xpm"
#include "stock_left_arrow.xpm"
#include "stock_right_arrow.xpm"
#include "aficon.xpm"
enum { AFHELP_CLOSE, AFHELP_BACK,
AFHELP_FORWARD };
BEGIN_EVENT_TABLE( AFHelp, wxFrame
)
EVT_TOOL( AFHELP_BACK, AFHelp::OnTool )
EVT_TOOL( AFHELP_FORWARD, AFHelp::OnTool )
EVT_TOOL( AFHELP_CLOSE, AFHelp::OnTool )
EVT_CLOSE( AFHelp::OnCloseFrame )
END_EVENT_TABLE();
AFHelp::AFHelp(const wxString
&zipfile)
: wxFrame(NULL, -1, "Commhost Help",
wxDefaultPosition, wxSize(600, 600))
{
#ifdef __WXMSW__
SetIcon( wxIcon("aficon") );
#else
SetIcon( wxIcon( aficon_xpm ) );
#endif
CreateStatusBar(1);
mZipFilePath = zipfile;
mToolBar = CreateToolBar();
mToolBar->AddTool( AFHELP_CLOSE, wxBitmap(
stock_close_xpm ), "Close Help" );
mToolBar->AddTool( AFHELP_BACK, wxBitmap(
stock_left_arrow_xpm ), "Go Back" );
mToolBar->AddTool( AFHELP_FORWARD, wxBitmap(
stock_right_arrow_xpm ), "Go Forward" );
mToolBar->SetToolBitmapSize(wxSize(24,
24));
mToolBar->Realize();
mHtml
= new wxHtmlWindow( this );
mHtml->SetRelatedFrame(this,
"Commhost Help : %s");
mHtml->SetRelatedStatusBar(0);
mHtml->LoadPage(mZipFilePath);
}
AFHelp::~AFHelp()
{
/* nothing to do
here */
}
void AFHelp::OnTool(wxCommandEvent
&evt)
{
switch(evt.GetId())
{
case AFHELP_CLOSE:
Hide();
break;
case AFHELP_BACK:
mHtml->HistoryBack();
break;
case AFHELP_FORWARD:
mHtml->HistoryForward();
default:
break;
}
}
void AFHelp::OnCloseFrame(wxCloseEvent
&evt)
{
Hide();
evt.Veto();
}
dlportio.h
/****************************************************************************
* @doc INTERNAL
* @module dlportio.h |
*
*
* <cp> Copyright 1996-1999
Scientific Software Tools, Inc.<nl>
* All Rights Reserved.<nl>
* DriverLINX is a registered trademark
of Scientific Software Tools, Inc.
*
* Win32 Prototypes for DriverLINX Port
I/O
*
* @comm
* Author: RoyF<nl>
* Date:
09/26/96 14:08:58
*
* @group Revision History
* @comm
* $Revision: 2 $
* <nl>
* $Log: /DLPortIO/API/DLPORTIO.H $
*
* 2 3/03/99 5:25p Kevind
* Removed any
reference for customer to call us when encountering bugs,
* also
removed our old address info.
*
* 1 9/27/96 2:03p Royf
* Initial revision.
*
****************************************************************************/
#ifndef DLPORTIO_H
#define DLPORTIO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef IN
#define IN
#endif
#define DLPORT_API _stdcall
UCHAR DLPORT_API
DlPortReadPortUchar(
IN
);
USHORT DLPORT_API
DlPortReadPortUshort(
IN
);
ULONG DLPORT_API
DlPortReadPortUlong(
IN
);
VOID DLPORT_API
DlPortReadPortBufferUchar(
IN
IN PUCHAR Buffer,
IN ULONG Count
);
VOID DLPORT_API
DlPortReadPortBufferUshort(
IN
IN PUSHORT Buffer,
IN ULONG Count
);
VOID DLPORT_API
DlPortReadPortBufferUlong(
IN
IN PULONG Buffer,
IN ULONG Count
);
VOID DLPORT_API
DlPortWritePortUchar(
IN
IN UCHAR Value
);
VOID DLPORT_API
DlPortWritePortUshort(
IN
IN USHORT Value
);
VOID DLPORT_API
DlPortWritePortUlong(
IN
IN ULONG Value
);
VOID DLPORT_API
DlPortWritePortBufferUchar(
IN
IN PUCHAR Buffer,
IN ULONG Count
);
VOID DLPORT_API
DlPortWritePortBufferUshort(
IN
IN PUSHORT Buffer,
IN ULONG Count
);
VOID DLPORT_API
DlPortWritePortBufferUlong(
IN
IN PULONG Buffer,
IN ULONG Count
);
#ifdef __cplusplus
}
#endif
#endif // DLPORTIO_H
array.h
#ifndef __array_h
#define __array_h
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include "vector.h"
template <class T>
class Array
{
public:
Array(int size = 5);
Array
&operator= (const Array &array);
T operator[] (int i) const;
T &operator[] (int i);
void prepend(const T &s);
void append(const T &s);
void insert(const T &s, int index);
int find(const T &s);
void remove(const T &s);
void remove(int index);
void clear();
void preAlloc(int size);
int count() const;
int length() const;
int capacity() const;
static Array make(int n, ...);
T *data();
private:
Vector<T>
items;
int n_items;
};
////////////////////////////////////////////////////////////
// templated implementation
template <class T>
Array<T>::Array(int size)
{
n_items = 0;
if (size > 0)
items.resize(size);
}
template <class T>
Array<T> &Array<T>::operator=
(const Array &array)
{
if (this != &array)
{
items.resize(array.length());
n_items = array.length();
for (int i=0;i<items.length();i++)
items[i] = array.items[i];
}
return *this;
}
template <class T>
T Array<T>::operator[] (int
i) const
{
assert( i >= 0 && i < n_items );
return items[i];
}
template <class T>
T &Array<T>::operator[]
(int i)
{
assert( i >= 0 && i < n_items );
return items[i];
}
template <class T>
void Array<T>::prepend(const T
&s)
{
insert(s, 0);
}
template <class T>
void Array<T>::append(const T &s)
{
int last_location = n_items;
if (items.length() < n_items + 1)
items.resize(items.length() + 10);
items[last_location] = s;
n_items++;
}
template <class T>
void Array<T>::insert(const T &s,
int index)
{
assert( index >=0 && index <= items.length()
);
if (items.length() < n_items + 1)
items.resize(items.length() + 10);
for (int i=n_items; i > index; i--)
items[i] = items[i-1];
items[index] = s;
n_items++;
}
template <class T>
int Array<T>::find(const T &s)
{
for (int i=0;i<n_items;i++)
if (s == items[i])
return i;
return -1;
}
template <class T>
void Array<T>::remove(const T &s)
{
int index = find(s);
if (index >= 0)
remove(index);
}
template <class T>
void Array<T>::remove(int index)
{
assert(index >= 0 && index < n_items);
for (int i=index;i<n_items-1;i++)
items[i] = items[i+1];
n_items--;
}
template <class T>
void Array<T>::clear()
{
n_items = 0;
}
template <class T>
void Array<T>::preAlloc(int size)
{
if (size > items.length())
items.resize(size);
}
template <class T>
int Array<T>::length() const
{
return n_items;
}
template <class T>
int Array<T>::count() const
{
return n_items;
}
template <class T>
int Array<T>::capacity() const
{
return items.length();
}
template <class T>
Array<T> Array<T>::make(int
n, ...)
{
char *str;
Array sa;
va_list args;
va_start(args, n);
for (int i=0;i<n;i++)
{
str = va_arg(args, char*);
sa.append( str );
}
va_end(args);
return sa;
}
template <class T>
T *Array<T>::data()
{
return items.data();
}
#endif
vector.h
#ifndef __vector_h
#define __vector_h
#include <assert.h>
template <class type>
class Vector
{
public:
Vector();
Vector(int size);
Vector(int size, const type &fill);
Vector(const Vector &vec);
~Vector();
void clear();
const Vector &operator= (const Vector &vec);
type &operator[] (int i);
const type &operator[] (int i) const;
type &at(int i);
const type &at(int i) const;
bool resize(int new_size, bool copy = true);
int length() const;
int size() const;
type *data();
private:
int t_size;
type *t_array;
};
////////////////////////////////////////////////////////////
// templated implementation
template <class type>
Vector<type>::Vector()
{
t_size = 0;
t_array = NULL;
}
template <class type>
Vector<type>::Vector(int
size)
{
t_size = size;
t_array = new type[t_size];
}
template <class type>
Vector<type>::Vector(int
size, const type &fill)
{
t_size = size;
t_array = new type[t_size];
for (int i=0; i < t_size; i++)
t_array[i]
= fill;
}
template <class type>
Vector<type>::Vector(const
Vector &vec)
{
t_size = vec.length();
t_array = new type[t_size];
for (int i=0; i < t_size; i++)
t_array[i]
= vec.t_array[i];
}
template <class type>
Vector<type>::~Vector()
{
delete [] t_array;
}
template <class type>
void Vector<type>::clear()
{
if (t_array)
delete [] t_array;
t_array = NULL;
t_size = 0;
}
template <class type>
const Vector<type>
&Vector<type>::operator= (const Vector &vec)
{
if (this != &vec)
{
delete [] t_array;
t_size = vec.length();
t_array =
new type[t_size];
for (int i=0;i<t_size;i++)
t_array[i]
= vec.t_array[i];
}
return *this;
}
template <class type>
type &Vector<type>::operator[]
(int i)
{
assert( i >= 0 && i < t_size);
return t_array[i];
}
template <class type>
const type
&Vector<type>::operator[] (int i) const
{
assert( i >= 0 && i < t_size);
return t_array[i];
}
template <class type>
type &Vector<type>::at (int i)
{
assert( i >= 0 && i < t_size);
return t_array[i];
}
template <class type>
const type &Vector<type>::at (int
i) const
{
assert( i >= 0 && i < t_size);
return t_array[i];
}
template <class type>
bool Vector<type>::resize(int
new_size, bool copy)
{
int num_to_copy = new_size < t_size ? new_size : t_size;
type *buf = new type[new_size];
if (copy)
for (int i=0;i<num_to_copy;i++)
buf[i] = t_array[i];
delete [] t_array;
t_size =
new_size;
t_array = buf;
return t_array != NULL;
}
template <class type>
int Vector<type>::length() const
{
return t_size;
}
template <class type>
int Vector<type>::size() const
{
return length();
}
template <class type>
type *Vector<type>::data()
{
return t_array;
}
#endif