Board index » cppbuilder » A really stupid Question - how to build a library

A really stupid Question - how to build a library


2004-10-06 02:29:47 AM
cppbuilder68
I cannot for the life of me find how to build a library in any of my builder
books or the help window.... I used to know how with the old Unix compiler
but have now forgotten. I'm not even sure I should be building a library vs
another .cpp file that is loaded with the main.cpp file as an .obj. A
library would be better though for how I want it to look for the people who
will be using it.
What I have are some functions that initialize and use an IO board. These
functions never change and it is confusing for the students to have to
include them in the programs they have to write. We have reached critical
mass in our lab and to simplify I want these routines to function much as
any other C function would. That is make the source code invisible to the
user but the functions themselves easily accessible by just including a
library or linking to an object file.
I can't even remember if I have to have a Main() for a lib.... so that is
where I am at and if someone can point me in the right direction or give me
a simple run down, it would be appreciated.
 
 

Re:A really stupid Question - how to build a library

You are asking about C++ Builder but have posted in the newsgroup for
the old, 1997, Borland C++ compiler. Please post C++ Builder
questions in C++ Builder newsgroups, newsgroups with the word
'cppbuilder' in their name. For example:
borland.public.cppbuilder.ide
. Ed
 

Re:A really stupid Question - how to build a library

Nope. I don't want to do this in builder. This is for a DOS program. I
meant Borland not Builder. Sorry.
"Ed Mulroy [TeamB]" < XXXX@XXXXX.COM >wrote in message
Quote
You are asking about C++ Builder but have posted in the newsgroup for the
old, 1997, Borland C++ compiler. Please post C++ Builder questions in C++
Builder newsgroups, newsgroups with the word 'cppbuilder' in their name.
For example:

borland.public.cppbuilder.ide

. Ed


 

{smallsort}

Re:A really stupid Question - how to build a library

From the command line
tlib /C libname.lib -+file1.obj -+file2.obj +-file3.obj {etc}
where -+ means replace so when you first create the library it will
give you a warning that the files did not already exist in the
library.
From a response file
tlib /C libname.lib @respfile.txt
where respfile.txt contains
-+file1.obj &
-+file2.obj &
-+file3.obj
Note that the & line continuation character must be preceeded by a
space.
From the IDE I do not remember the location of the library selection,
but could not tell you even if I did because it varies among versions
and you have not mentioned what version you are using. Look at the
target types that you can create. Use the help.
. Ed
Quote
D Kat wrote in message
news:4162f33b$ XXXX@XXXXX.COM ...

Nope. I don't want to do this in builder. This is for a DOS
program. I meant Borland not Builder. Sorry.
 

Re:A really stupid Question - how to build a library

"Ed Mulroy [TeamB]" < XXXX@XXXXX.COM >wrote in message
Quote
From the command line

tlib /C libname.lib -+file1.obj -+file2.obj +-file3.obj {etc}

where -+ means replace so when you first create the library it will give
you a warning that the files did not already exist in the library.

From a response file

tlib /C libname.lib @respfile.txt

where respfile.txt contains

-+file1.obj &
-+file2.obj &
-+file3.obj

Note that the & line continuation character must be preceeded by a space.

From the IDE I do not remember the location of the library selection, but
could not tell you even if I did because it varies among versions and you
have not mentioned what version you are using. Look at the target types
that you can create. Use the help.

. Ed

>D Kat wrote in message
>news:4162f33b$ XXXX@XXXXX.COM ...
>
>Nope. I don't want to do this in builder. This is for a DOS program. I
>meant Borland not Builder. Sorry.
OK, this all looks familiar.... Thank you.
Now on to a question about ..... what can and cannot go in the lib file..
Where to begin.
The programs written by the students opens a binary file that is then output
to a D/A.
I would like the Library to have in it the function that initializes the
board, resets the computer vectors after the board is done with, etc.
Ideally I would like to have the interrupt function in the library itself
but this is going to be using the file being opened by the program which the
student writes that uses the library... In addition I'm using double
buffering so using a pointer in a simple sense won't work... Should I
declare the double array FileBuffer that is used to be an external in the
Library? I'm currently using a pointer that is assigned the active buffer
each time an end of buffer is reached..... Then of course there are the
counters (ticks for each call to the interrupt) and other variables that are
needed by the main program. I seem to be going around in circles on this.
I think I have just convinced myself that this routine cannot go into the
library. Thoughts or advice would be appreciated.
//==========================================================================
//interrupt routine with play and button catch
//=======================================================================
void __interrupt i_service(...)// Daq801 interrupt service routine
{
disable(); // disable the interrupts
int button,i; // button iterator
unsigned char PA_buttons,PC_buttons; // temp holding register for current
buttons
inp(I_STATUS); // read the interrupt status register and clear interrupt
for (i=0;i<TIMERS;i++)
{
counter[i]++; // increment all up-counters
if (timer[i] !=0)
{ timer[i]--;} // decrement ?32 timer array elements if not zero!
}
if (counter[0] == file_length)PLAYFLAG=0;
if (PLAYFLAG==1)
{
if (counter[1] == (readlength[playndx]-1))
{//if at end of buffer point to next buffer
playndx++;
if(playndx==NUMBUF)playndx=0;//next buffer at 0 if beyond last buffer
if(readlength[playndx]<2) PLAYFLAG=0;//if buffer empty - stop play
else{ //else setup to play next buffer and read next buffer
da_point = &wavebuffer[playndx][0]; //point to next buffer to play
counter[1]=0;//counter for this buffer set to beginning
READ = 1;
}// read flag: buffer is empty ->fill buffer
}
outpw(DA_0,*da_point);
outpw(DA_1,*da_point++);
}
if (BUTTONFLAG)
{
PA_buttons=(inp(PA)); // freeze data
if (PA_buttons != MASK)// process following path only if one or more
{ // buttons were pressed!
for (button=0;button<NBUTTONS-4;button++)
{
if ((PA_buttons &(1<<button))==0 && counter_time[button]==0)
{
press_count++; // increment press counter
counter_time[button]=counter[0]; // record response time
}
}
}
PC_buttons=(inp(PC)&UPPER_MASK); // freeze data & mask off upper buttons
if ((PC_buttons) != UPPER_MASK)// process following path only if one or
more
{ // buttons were pressed!
for (button=4;button<NBUTTONS-4;button++)
{
if ((PC_buttons &(1<<button))==0 && counter_time[button+4]==0)
{
press_count++; // increment press counter
counter_time[button+4]=counter[0]; // record response time
}
}
}
}
outp(0x20,EOI_IRQ3); // clear the 8259 interrupt
enable(); // re-enable the interrupts
} // end of interrupt service routine
 

Re:A really stupid Question - how to build a library

I am disturbed by how much processing is in that ISR (interrupt
service routine) and how long it keeps interrupts off. I hope you are
running it on a fast machine.
Assuming that this or something like it is what you mean by DAQ801
www.shorl.com/bujujulogufa
AKA
www.netfusion.co.za/Network_Solutions/Quatech/products/daq801.htm
then it has several K of data buffering so you'll probably get away
with so much processing but I suggest that you think about how much of
that processing you want to do prior to re-enabling interrupts. From
a quick look at the code, it looks like you are doing things like
incrementing whole array in a loop and then using only the first two
elements in the array to develop port outputs, waiting until all that
is done before reading another port (to set PC_buttons) and then doing
another loop prior to clearing the 8259 and renabling interrupts.
Yes of course you can put an object file containing an ISR into a
library.
You can provide a header file which declares the needed arrays as
extern and have library code declare the instances of the arrays. In
the file containing the ISR you can use #pragma exit to register a
function also in the library which cleans up at the end should the
student forget and #pragma startup to register one that does whatever
you want to force being done prior to main being called. Just
remember to provide the functions referenced by the pragmas in object
files in the library.
If you are going to show that code to students it might be useful to
not encourage bad habits. You might want to alter all but one of the
increments and all of the decrements to pre instead of post. Post is
expensive when used with objects and should not be allowed to be a
habit. Similarly you might want to change the all-caps variable
names. All-caps normally are macros (and macros in that code are
all-caps). Things like that are often viewed in industry as a sign of
amateur behavior. You want your students to look good to industry.
. Ed
Quote
D Kat wrote in message
news:41645253$ XXXX@XXXXX.COM ...

Now on to a question about ..... what can and cannot go in the lib
file..

Where to begin.

The programs written by the students opens a binary file that is
then output to a D/A.

I would like the Library to have in it the function that
initializes the board, resets the computer vectors after the board
is done with, etc.

Ideally I would like to have the interrupt function in the library
itself but this is going to be using the file being opened by the
program which the student writes that uses the library... In
addition I'm using double buffering so using a pointer in a simple
sense won't work... Should I declare the double array FileBuffer
that is used to be an external in the Library? I'm currently using
a pointer that is assigned the active buffer each time an end of
buffer is reached..... Then of course there are the counters (ticks
for each call to the interrupt) and other variables that are needed
by the main program. I seem to be going around in circles on this.

I think I have just convinced myself that this routine cannot go
into the library. Thoughts or advice would be appreciated.

//==========================================================================
//interrupt routine with play and button catch
//=======================================================================
void __interrupt i_service(...)// Daq801 interrupt service routine
{
disable(); // disable the interrupts

int button,i; // button iterator
unsigned char PA_buttons,PC_buttons; // temp holding register for
current buttons

inp(I_STATUS); // read the interrupt status register and clear
interrupt

for (i=0;i<TIMERS;i++)
{
counter[i]++; // increment all up-counters
if (timer[i] !=0)
{ timer[i]--;} // decrement ?32 timer array elements if not
zero!
}
if (counter[0] == file_length)PLAYFLAG=0;
if (PLAYFLAG==1)
{
if (counter[1] == (readlength[playndx]-1))
{//if at end of buffer point to next buffer
playndx++;
if(playndx==NUMBUF)playndx=0;//next buffer at 0 if beyond last
buffer
if(readlength[playndx]<2) PLAYFLAG=0;//if buffer empty - stop
play
else{ //else setup to play next buffer and read next buffer
da_point = &wavebuffer[playndx][0]; //point to next buffer to
play
counter[1]=0;//counter for this buffer set to beginning
READ = 1;
}// read flag: buffer is empty ->fill buffer
}
outpw(DA_0,*da_point);
outpw(DA_1,*da_point++);
}
if (BUTTONFLAG)
{
PA_buttons=(inp(PA)); // freeze data
if (PA_buttons != MASK)// process following path only if one or
more
{ // buttons were pressed!
for (button=0;button<NBUTTONS-4;button++)
{
if ((PA_buttons &(1<<button))==0 && counter_time[button]==0)
{
press_count++; // increment press counter
counter_time[button]=counter[0]; // record response time
}
}
}
PC_buttons=(inp(PC)&UPPER_MASK); // freeze data & mask off upper
buttons
if ((PC_buttons) != UPPER_MASK)// process following path only if
one or more
{ // buttons were pressed!
for (button=4;button<NBUTTONS-4;button++)
{
if ((PC_buttons &(1<<button))==0 && counter_time[button+4]==0)
{
press_count++; // increment press counter
counter_time[button+4]=counter[0]; // record response time
}
}
}
}
outp(0x20,EOI_IRQ3); // clear the 8259 interrupt
enable(); // re-enable the interrupts
} // end of interrupt service routine
 

Re:A really stupid Question - how to build a library

"Ed Mulroy [TeamB]" < XXXX@XXXXX.COM >wrote in message
Quote
I am disturbed by how much processing is in that ISR (interrupt
service routine) and how long it keeps interrupts off. I hope you are
running it on a fast machine.
Machines are fast. The interrupt rate is 16K at it's fastest (16000/sec).
I used to do something similar at 10K on a UNIX OS. The only code that
actually takes significant time I believe is the outpw. This is standard
DOS exe. Nothing happens in the ISR unless the PLAYFLAG and/or the
BUTTONFLAG are true. Each is set to true then a while loop that only reads
in a new buffer when the flag is triggered runs until the flags are false.
BUTTONFLAG = true;
PLAYFLAG = true;
while(PLAYFLAG){if(READFLAG)get_next_buffer;}
//tad more complex than this but not much - 2 buffers about 4096
while(counter<(MAXWAIT+numsamples) || BUTTONFLAG);
BUTTONFLAG = false;
It is the DAQ802 but I'm not using DMA. what we do often requires doing one
sample of output at a time.
Quote
Assuming that this or something like it is what you mean by DAQ801
www.shorl.com/bujujulogufa
AKA
www.netfusion.co.za/Network_Solutions/Quatech/products/daq801.htm
then it has several K of data buffering so you'll probably get away
with so much processing but I suggest that you think about how much of
that processing you want to do prior to re-enabling interrupts. From
a quick look at the code, it looks like you are doing things like
incrementing whole array in a loop and then using only the first two
elements in the array to develop port outputs, waiting until all that
is done before reading another port (to set PC_buttons) and then doing
another loop prior to clearing the 8259 and renabling interrupts.

Yes of course you can put an object file containing an ISR into a
library.

You can provide a header file which declares the needed arrays as
extern and have library code declare the instances of the arrays. In
the file containing the ISR you can use #pragma exit to register a
function also in the library which cleans up at the end should the
student forget and #pragma startup to register one that does whatever
you want to force being done prior to main being called. Just
remember to provide the functions referenced by the pragmas in object
files in the library.

If you are going to show that code to students it might be useful to
not encourage bad habits. You might want to alter all but one of the
increments and all of the decrements to pre instead of post. Post is
expensive when used with objects and should not be allowed to be a
habit.
Similarly you might want to change the all-caps variable
names. All-caps normally are macros (and macros in that code are
all-caps). Things like that are often viewed in industry as a sign of
amateur behavior. You want your students to look good to industry.

. Ed
we are a science research lab that knows just enough about programming to
get by (no one is going to see our code other than us). The all caps is
from Unix days - maybe fortran - can't remember... where all caps were used
for #define which is how we used to do constants (aren't you proud of me
that I now use const rather than #define for my Constants :) ).... But I
do want to learn what I can and very much appreciate your effort to educate.
I now have to go read about #pragma, post and pre increment/decrement,
figure out how to use decrement given that my mind set is to make the
variable change after the fact rather than before...., etc.
Thank you again.
Quote
>D Kat wrote in message
>news:41645253$ XXXX@XXXXX.COM ...
>
>Now on to a question about ..... what can and cannot go in the lib
>file..
>
>Where to begin.
>
>The programs written by the students opens a binary file that is
>then output to a D/A.
>
>I would like the Library to have in it the function that
>initializes the board, resets the computer vectors after the board
>is done with, etc.
>
>Ideally I would like to have the interrupt function in the library
>itself but this is going to be using the file being opened by the
>program which the student writes that uses the library... In
>addition I'm using double buffering so using a pointer in a simple
>sense won't work... Should I declare the double array FileBuffer
>that is used to be an external in the Library? I'm currently using
>a pointer that is assigned the active buffer each time an end of
>buffer is reached..... Then of course there are the counters (ticks
>for each call to the interrupt) and other variables that are needed
>by the main program. I seem to be going around in circles on this.
>
>I think I have just convinced myself that this routine cannot go
>into the library. Thoughts or advice would be appreciated.
>
>
//==========================================================================
>//interrupt routine with play and button catch
>
//=======================================================================
>void __interrupt i_service(...)// Daq801 interrupt service routine
>{
>disable(); // disable the interrupts
>
>int button,i; // button iterator
>unsigned char PA_buttons,PC_buttons; // temp holding register for
>current buttons
>
>inp(I_STATUS); // read the interrupt status register and clear
>interrupt
>
>for (i=0;i<TIMERS;i++)
>{
>counter[i]++; // increment all up-counters
>if (timer[i] !=0)
>{ timer[i]--;} // decrement ?32 timer array elements if not
>zero!
>}
>if (counter[0] == file_length)PLAYFLAG=0;
>if (PLAYFLAG==1)
>{
>if (counter[1] == (readlength[playndx]-1))
>{//if at end of buffer point to next buffer
>playndx++;
>if(playndx==NUMBUF)playndx=0;//next buffer at 0 if beyond last
>buffer
>if(readlength[playndx]<2) PLAYFLAG=0;//if buffer empty - stop
>play
>else{ //else setup to play next buffer and read next buffer
>da_point = &wavebuffer[playndx][0]; //point to next buffer to
>play
>counter[1]=0;//counter for this buffer set to beginning
>READ = 1;
>}// read flag: buffer is empty ->fill buffer
>}
>outpw(DA_0,*da_point);
>outpw(DA_1,*da_point++);
>}
>if (BUTTONFLAG)
>{
>PA_buttons=(inp(PA)); // freeze data
>if (PA_buttons != MASK)// process following path only if one or
>more
>{ // buttons were pressed!
>for (button=0;button<NBUTTONS-4;button++)
>{
>if ((PA_buttons &(1<<button))==0 && counter_time[button]==0)
>{
>press_count++; // increment press counter
>counter_time[button]=counter[0]; // record response time
>}
>}
>}
>PC_buttons=(inp(PC)&UPPER_MASK); // freeze data & mask off upper
>buttons
>if ((PC_buttons) != UPPER_MASK)// process following path only if
>one or more
>{ // buttons were pressed!
>for (button=4;button<NBUTTONS-4;button++)
>{
>if ((PC_buttons &(1<<button))==0 && counter_time[button+4]==0)
>{
>press_count++; // increment press counter
>counter_time[button+4]=counter[0]; // record response time
>}
>}
>}
>}
>outp(0x20,EOI_IRQ3); // clear the 8259 interrupt
>enable(); // re-enable the interrupts
>} // end of interrupt service routine


 

Re:A really stupid Question - how to build a library

D Kat wrote:
Quote
each time an end of buffer is reached..... Then of course there are the
counters (ticks for each call to the interrupt) and other variables that are
needed by the main program. I seem to be going around in circles on this.
Forget for a minute what the Main program needs.....
Put everything the Library code needs, in the Library.
Then, think about what the Main program needs to know.
Anything that the Main doesn't need to know, make static.
Probably readlength[] and playndx;
static int readlength[whatever];
static int playndx;
Everything the Main program needs to know, declare in a Header file as
extern.
extern int TIMERS;
extern int counter[];
extern int timer[];
Quote
int button,i; // button iterator
unsigned char PA_buttons,PC_buttons; // temp holding register for current
for (i=0;i<TIMERS;i++)
Are there more than 2 timers?
Is TIMERS a fixed value?
If so, then unroll the loop for much better speed (important for ISRs)
Quote
if (counter[0] == file_length)PLAYFLAG=0;
Program defensively, check>= instead of ==
Quote
if (PLAYFLAG==1)
{
if (counter[1] == (readlength[playndx]-1))
Program defensively, check>= instead of ==
Quote
{//if at end of buffer point to next buffer
playndx++;
if(playndx==NUMBUF)playndx=0;//next buffer at 0 if beyond last buffer
Program defensively, check>= instead of ==
Quote
if(readlength[playndx]<2) PLAYFLAG=0;//if buffer empty - stop play
else{ //else setup to play next buffer and read next buffer
da_point = &wavebuffer[playndx][0]; //point to next buffer to play
counter[1]=0;//counter for this buffer set to beginning
READ = 1;
}// read flag: buffer is empty ->fill buffer
}
This loops the output if the buffer is empty?
Quote
outpw(DA_0,*da_point);
outpw(DA_1,*da_point++);
}
 

Re:A really stupid Question - how to build a library

Note that I assumed from your message that you were creating code for
use by students. Upon re-reading the message I am not sure how I
formed that opinion. I have made more than a few bucks teaching
professors C++ and C who were assigned to teach language classes but
were only a few pages ahead (sometimes behind!) the students and
wanted to express caution about some things.
Quote
Machines are fast. The interrupt rate is 16K ...
You appear to have that issue well in hand.
Quote
... I now have to go read about #pragma,
post and pre increment/decrement,
figure out how to use decrement given
that my mind set is to make the
variable change after the fact rather than before...., etc.
#pragma :
This is a method for giving the compiler a command, analagous to a
command line option but in the code.
For example:
#pragma startup function1
will cause function1 to be added to the list of functions to be called
in the startup/initialization process prior to when main is called.
As shown it would be called after all the default initialization is
completed.
#pragma exit function1
does the same except at the end, with function1 being called prior to
any of the compiler's ending/cleanup functions.
Post and pre increment/decrement:
++var
Increment var. The value used in the expression is the new value.
var++
Increment var and save the value, but use the original value of var in
the expression.
Same comments and syntax with -- except that it decrements instead of
incrementing.
Consider the differences between what the loops do in this code:
int var;
for (var = 6; var < 22; var++)
function_A();
for (var = 6; var < 22; ++var)
function_A();
The logical operations caused by these loops differ in that the first
loop requires that a copy of the original value of 'var' must be
formed, saved somewhere and loaded again after the increment and store
of the new value.
Restating:
There is some additional overhead associated with the post increment
(the var++). Compiler writers have long since caught on to this
common bad habit of programmers and optimize this specific usage for
integers, but the syntax is the same if 'var' is an object other than
an integral type.
When 'var' is a class or structure, not a uncommon situation in C++,
post-increment forces construction of a temporary instance of the
class to capture the original state, save of the temporary somewhere
(possibly causing an allocation call), call the post increment
function, restore the temporary test and test, save the test results,
possibly a de-allocation call for the temporary - BIG overhead. Using
var++ instead of ++var is not a good habit.
. Ed
Quote
dkat wrote in message
news: XXXX@XXXXX.COM ...

... we are a science research lab that knows just enough
about programming to get by (no one is going to see our
code other than us). The all caps is from Unix days -
maybe fortran - can't remember... where all caps were used
for #define which is how we used to do constants (aren't
you proud of me that I now use const rather than #define
for my Constants :) ).... But I do want to learn what I can
and very much appreciate your effort to educate.
I now have to go read about #pragma, post and pre
increment/decrement, figure out how to use decrement given
that my mind set is to make the variable change after the
fact rather than before...., etc.

Thank you again.
 

Re:A really stupid Question - how to build a library

"Bob Gonder" < XXXX@XXXXX.COM >wrote in message
Quote
D Kat wrote:

>each time an end of buffer is reached..... Then of course there are the
>counters (ticks for each call to the interrupt) and other variables that
>are
>needed by the main program. I seem to be going around in circles on this.

Forget for a minute what the Main program needs.....
Put everything the Library code needs, in the Library.
Then, think about what the Main program needs to know.
Anything that the Main doesn't need to know, make static.
Probably readlength[] and playndx;
static int readlength[whatever];
static int playndx;

Everything the Main program needs to know, declare in a Header file as
extern.
extern int TIMERS;
extern int counter[];
extern int timer[];

>int button,i; // button iterator
>unsigned char PA_buttons,PC_buttons; // temp holding register for current
All sounds good (that is clear and easy to understand..)
Quote
>for (i=0;i<TIMERS;i++)

Are there more than 2 timers?
Is TIMERS a fixed value?
If so, then unroll the loop for much better speed (important for ISRs)
The timer variable is an array whose size in history had varied because
different programs used it in different ways.
Each time the ISR is called this variable if it is greater than ZERO counts
down (most often used for something such as a delay or wait function - we
use an LCD display that has to have delays between commands written out to
it for example and we have to have delays between trials). In addition
there has to be an array of counters the count up (clocks). This would be
used the keep track of where in time a button was pushed relative to when
the first sample of an auditory file was played.
A quick and dirty discription of a program we might have to write -
A speech file is played. Associated with each speech file is a picture that
must be presented when the second syllable of the speech file is reached
(there would be an array of speech names and associated with that an array
of display times). So on file1 when the counter is equal to Time1 a picture
is shown.
Quote
>if (counter[0] == file_length)PLAYFLAG=0;

Program defensively, check>= instead of ==
PLAYFLAG Should be a BOOL but I
Quote
>if (PLAYFLAG==1)
>{
>if (counter[1] == (readlength[playndx]-1))
Program defensively, check>= instead of ==
that code would not work. Basically the flag to read in the next buffer and
switch buffers played should ONLY be set when the counter is at end of
buffer.
Quote
>{//if at end of buffer point to next buffer
>playndx++;
>if(playndx==NUMBUF)playndx=0;//next buffer at 0 if beyond last buffer

Program defensively, check>= instead of ==
If the playndx is>than NUMBUF then there is a serious error
Quote
>if(readlength[playndx]<2) PLAYFLAG=0;//if buffer empty - stop play
>else{ //else setup to play next buffer and read next buffer
>da_point = &wavebuffer[playndx][0]; //point to next buffer to play
>counter[1]=0;//counter for this buffer set to beginning
>READ = 1;
>}// read flag: buffer is empty ->fill buffer
>}

This loops the output if the buffer is empty?
the outpw should occur first. If I put it after the test of buffers, I
wrote it wrong.
It should be
/*************************************
Initialization = buffers filled; pointer to buffers set to buffer[0][0];
Flags set to appropriate falues ( 0 for READBUFFER and 1 for PLAYBUFFER and
GETBUTTONPUSH);
When in ISR
D/A OUT; Check place in buffer and if necessary set READBUFFERFLAG and
switch pointer to other buffer ; then check if Buttonboard has been pushed;
if counter == length of file set PLAYFLAG to 0;
in Play routine
while PLAYFLAG true - fill buffer if necessary and reset flag;
when PLAYFLAG false wait a few seconds to collect BUTTONPUSH
return to main (which will open file or files and call play)
/***********************************************
Quote

>outpw(DA_0,*da_point);
>outpw(DA_1,*da_point++);
>}

 

Re:A really stupid Question - how to build a library

"Ed Mulroy [TeamB]" < XXXX@XXXXX.COM >wrote in message
Quote
Note that I assumed from your message that you were creating code for use
by students. Upon re-reading the message I am not sure how I formed that
opinion. I have made more than a few bucks teaching professors C++ and C
who were assigned to teach language classes but were only a few pages
ahead (sometimes behind!) the students and wanted to express caution about
some things.
Post and pre increment/decrement:

++var
Increment var. The value used in the expression is the new value.

var++
Increment var and save the value, but use the original value of var in the
expression.

Same comments and syntax with -- except that it decrements instead of
incrementing.

Consider the differences between what the loops do in this code:

int var;

for (var = 6; var < 22; var++)
function_A();

for (var = 6; var < 22; ++var)
function_A();

The logical operations caused by these loops differ in that the first loop
requires that a copy of the original value of 'var' must be formed, saved
somewhere and loaded again after the increment and store of the new value.

Restating:
There is some additional overhead associated with the post increment (the
var++). Compiler writers have long since caught on to this common bad
habit of programmers and optimize this specific usage for integers, but
the syntax is the same if 'var' is an object other than an integral type.

When 'var' is a class or structure, not a uncommon situation in C++,
post-increment forces construction of a temporary instance of the class to
capture the original state, save of the temporary somewhere (possibly
causing an allocation call), call the post increment function, restore the
temporary test and test, save the test results, possibly a de-allocation
call for the temporary - BIG overhead. Using var++ instead of ++var is
not a good habit.

. Ed

Things are going well... I'm in the process of changing all the incrementing
code to pre rather than post....
Problem... I have a pointer to a character array that I'm incrementing ...
*message++
what is the proper way to deal with this? ++(*message) or what? It compiles
just fine as ++*message .... but that just seems... not right.
I'm also going back and forth on where to put the actual ISR since that
varies and I can see no way to make it do optional operations without
putting too much code in it.
For example... Some times we play one buffer out one channel and another out
the other (in effect stereo). Sometimes we play the same data point out of
both channels (mono)..... I am already getting clicks once in every great
while so I do not want to push it...... Unfortunately you can't create
different ISRs that are called depending on the argument list (overloading
?)... Sorry, thinking outloud to the room. It has been very helpful coming
here.
 

Re:A really stupid Question - how to build a library

D Kat wrote:
Quote
For example... Some times we play one buffer out one channel and another out
the other (in effect stereo). Sometimes we play the same data point out of
both channels (mono)..... I am already getting clicks once in every great
while so I do not want to push it...... Unfortunately you can't create
different ISRs that are called depending on the argument list (overloading
Your library might handle only stereo.
The application could either fill a single channel (leaving the other
NULL,), fill both channels with the same buffer (pass the same pointer
as both left and right channels), or pass in 2 different buffers for
full stereo.
 

Re:A really stupid Question - how to build a library

No, in the case of *message++ (the one post increment in your code
that is NOT better as a pre increment), the code is correct. You want
to increment but use the original value.
Had you wanted pre increment it would have been *++message, increment
the pointer and then take the value at the new address. ++*message
would increment the value at the address contained in the variable.
I am used to doing DOS ISR's on DOS-era machines and not on gigahertz
machines. On such machines one must be careful about the amount of
processing one does during the interrupt.
Quote
...Unfortunately you can't create different ISRs that are called
depending on the argument list ...
ISR's have no argument list controllable by you.
Of course you can have multiple ISR's. You already are doing
something like this:
start
call getvect and save the original vector
call setvect to set your ISR as the vector
run
at the end
call setvect to restore the original vector
I do not know anything limiting you from setting a new vector when you
change modes. You can have several ISR's and set whatever one you
wish to have right now.
. Ed
Quote
D Kat wrote in message
news:4165847e$ XXXX@XXXXX.COM ...

Things are going well... I'm in the process of changing all the
incrementing code to pre rather than post....
Problem... I have a pointer to a character array that I'm
incrementing ... *message++

what is the proper way to deal with this? ++(*message) or what? It
compiles just fine as ++*message .... but that just seems... not
right.

I'm also going back and forth on where to put the actual ISR since
that varies and I can see no way to make it do optional operations
without putting too much code in it.

For example... Some times we play one buffer out one channel and
another out the other (in effect stereo). Sometimes we play the
same data point out of both channels (mono)..... I am already
getting clicks once in every great while so I do not want to push it
...... Unfortunately you can't create different ISRs that are
called depending on the argument list (overloading ?)... Sorry,
thinking outloud to the room. It has been very helpful coming here.
 

Re:A really stupid Question - how to build a library

"Ed Mulroy [TeamB]" < XXXX@XXXXX.COM >wrote in message
Quote
Of course you can have multiple ISR's. You already are doing
something like this:

start
call getvect and save the original vector
call setvect to set your ISR as the vector
run
at the end
call setvect to restore the original vector

I do not know anything limiting you from setting a new vector when you
change modes. You can have several ISR's and set whatever one you
wish to have right now.

. Ed
OK, this is where I have a serious flaw in my understanding of how things
work. I had thought I could only have one ISR in my library for any
particular interrupt since I had thought declaring it basically started it
up.... I can't really wrap my head around this one... must think on it
longer. The ISR doesn't get called as a function or routine in the
program - it gets called by the interrupt.... that is it is event driven
rather than bumped off the stack (yes I'm using made up jargon ....). So
what I would do would be have different initialization routines that would
trigger different ISRs... (really sorry about not having the correct wording
here. Am I close?
 

Re:A really stupid Question - how to build a library

There are three kinds of interrupt
- ones generated by problems such as an invalid op-code
(a kind that we need not deal with here)
- ones generated by a software instruction (called software
interrupts)
- ones generated by signal at the processor's pins (called
hardware interrupts).
Interrupts are hardware assisted pre-emptive call instructions. They
wait for the current instruction to finish (for a step in the current
one for some instructions), save the processing address on the stack
and transfer control to an address whose value is an entry in a table
called the interrupt vector table. Each interrupt number has an entry
in the table, a table whose entries DOS set as it was initializing.
Most operating system functions under DOS are invoked by generating a
software interrupt and most of them involve interrupt 0x21 with a
value in the AH register specifying what function is to be performed.
This is called a DOS interrupt or more often a DOS function call.
When your DAC board generates an interrupt, control transfers to the
address in the interrupt vector table for that interrupt. Normally
that would be a set of code that merely returns from interrupt (code
that executes an IRET instruction).
To ask DOS to set an interrupt vector one places 0x25 into the AH
register, the interrupt number into the AL register, the interrupt
vector (address) into the DS and DX registers and do a DOS call,
generate a 0x21 interrupt (INT 0x21 or geninterrupt(0x21)). Note that
the DS register is used by your program for the segment address for
your data segment (base address of the up to 64K data block divided by
16) so one normally has to push DS onto the stack, set the value for
the vector, do the DOS call, then pop the value of DS off of the stack
to restore it.
To ask DOS to give you the current value of the interrupt vector you
place 0x35 in the AH register, the interrupt number in the AL register
and do a DOS call. The interrupt vector is returned in the ES and BX
registers.
The compiler provides functions to set and get interrupt vector
values, the functions setvect and getvect. They deal with the
vagarities of what registers need be saved and restored and calling
DOS.
An example of a program which uses interrupts for serial
communications under DOS is here: (not the best code, way too much
processing in the interrupt - it's meant as an example for how things
are done, not intended to illustrate production code)
ftp.nsk.su/pub/text-doc/ti/bc_cpp/ti445.zip
That is part fo the TI (Tech Info Document) archive at this page:
ftp.nsk.su/cgi-bin/bbs2html?pub/text-doc/ti/bc_cpp
. Ed
Quote
dkat wrote in message
news: XXXX@XXXXX.COM ...

OK, this is where I have a serious flaw in my understanding of
how things work. I had thought I could only have one ISR in my
library for any particular interrupt since I had thought
declaring it basically started it up.... I can't really wrap
my head around this one... must think on it longer. The ISR
doesn't get called as a function or routine in the program - it
gets called by the interrupt.... that is it is event driven
rather than bumped off the stack (yes I'm using made up jargon
....). So what I would do would be have different
initialization routines that would trigger different ISRs...
(really sorry about not having the correct wording here. Am I
close?