The program below, using the terminal I/O, works as expected, except for one inconsistency:
SimpleIDE Console screen:
Hello World!
How old are you? 22
So, you are 22 years old.
Linux box:
Hello World!
How old are you? 22
So, you are 22 years old.
Why do I get the empty line in the Console screen?
Ray
/**
* @file test3.cpp
* This is the main test3 program start point.
*/
#include <tinystream>
#include <propeller.h>
#define CR '\n'
using namespace std;
/**
* Main program function.
*/
int main(void)
{
int i;
waitcnt(CLKFREQ/6+CNT); /* Wait for console window */
cout << "Hello World!" << CR;
cout << "How old are you? ";
cin >> i; /* Waiting for some keyboard input */
cout << "So, you are ";
cout << i; /* This does a CR, you get an empty line below */
cout << " years old.";
cout << CR;
return 0;
}
OK, that did the trick, I just hope I remember to reset it for other stuff.
In the Simple Terminal Options, you have (14) Position Cursor (x), and (15) Position Cursor (y). What would the command look like to implement these? I want to try to do some cursor placement in the Terminal window.
In the Simple Terminal Options, you have (14) Position Cursor (x), and (15) Position Cursor (y). What would the command look like to implement these? I want to try to do some cursor placement in the Terminal window.
The Simple Terminal is supposed to be Parallax Serial Terminal (PST) compatible.
Some things like "Enter is NL", and "Swap Receive CR/NL" are provided to make it more generic.
There are differences between Windows and Linux/Unix that will never be resolved
The only reference that I know of is the Parallax Serial Terminal.spin object.
Guess that's the subject for another chapter in the SimpleIDE User Guide ....
Most of the PST commands require a single character like:
// home();
putchar(1); // send cursor home command
Three are a little more complicated:
// position(x,y)
putchar(2); // position x,y command
putchar(x);
putchar(y);
// position(x)
putchar(14); // position x command
putchar(x);
// position(y)
putchar(15); // position y command
putchar(y);
So far I have found that the number 10 does not work correctly for the x value in (14), it just sets it to a 0 position. Not sure about the x value in (2) when you use the number 10. Have not checked all of the y positions yet.
The putchar() works fine, for cursor placement, but I could not get it to work using cout. I tried cout << (14) << (9), but I just get bunch of strange numbers, and no cursor movement.
The value 10 is used to represent a newline. This is most likely generating a CR and a LF, which are 13 and 10. If you use the normal standard I/O you can disable this feature. I don't know if this is possible with the tiny library.
Below is a program that I put together to see how I would start to develop a C++ program. Of course it looks more like a plain C program at the moment. I decided to use the dreaded 'goto' just see if, and how it works. I also tried to implement a cin that would take in a string, just could not get that to work, maybe it's a limitation of tinystream? Basically:
string mystr;
getline(cin,mystr)
is what I used, but could not get it to work, I tried both #include <string>, and #include <string.h>.
Now, for the C++ experts, what functions could be converted into objects? I was thinking maybe the control of the pins? Somehow create an object with high(), low(), ..., etc?
The settings for this are Board Type - Quickstart; Compiler Type - C++; Memory Model - CMM; Optimization - Os Size; Linker - Tiny Lib. Also, Enter is NL, unchecked, in the terminal options menu.
I also ran this program using Tera Term, and PuTTY, which did not run into any problems, of course the terminal screen control did not work. You would think their would be a standard for that by now.
What else? Oh Any ideas as to how I would test out reading and writing to an SD card, using <tinystream>? What are some options?
Ray
/**
* @file test4.cpp
* This is the main test4 program start point.
* This is a limited board check program using a UI.
**/
#include <tinystream>
#include <propeller.h>
#include <unistd.h>
#define CR '\n'
using namespace std;
void TitleBar(void)
{
// cout << "This is test4.cpp" << CR;
cout << "Menu " << CR;
cout << "1. Check board" << CR;
}
void high(int WCpin)
{
unsigned int bits = 1 << WCpin;
DIRA |= bits;
OUTA |= bits;
}
void low(int WCpin)
{
unsigned int mask = 1 << WCpin;
DIRA |= mask;
OUTA &= ~mask;
}
void LiteUm(void)
{
high(16), high(17), high(18), high(19), high(20), high(21), high(22), high(23);
usleep(1000000);
low(16), low(17), low(18), low(19), low(20), low(21), low(22), low(23);
}
void GetBoardInfo()
{
int i;
top:
cout << "Board Type: " << CR;
cout << "1. QuickStart 2. C3 3. DNA-xxx " << CR;
cout << "Choice: ";
cin >> i;
if (i > 3)
{
goto top;
}
if (i == 1)
{
cout << "You have a QuickStart";
LiteUm();
}
if (i == 2)
{
cout << "You have a C3";
}
if (i == 3)
{
cout << "You have a DNA-xxx";
}
}
void ClrScrn(void)
{
putchar(0);
putchar(2);
putchar(0);
putchar(0);
}
/**
* Main program function.
**/
int main(void)
{
unsigned long n;
char z;
int x;
waitcnt(CLKFREQ/6+CNT); /* Wait for terminal catch up. */
TitleBar();
do
{
cout << "Choice: ";
cin >> x;
if (x == 1)
{
GetBoardInfo();
}
cout << CR << "Quit? (y/n) ";
cin >> z;
if (z == 'y')
{
ClrScrn();
n = 0;
}
if (z == 'n')
{
ClrScrn();
n = 1;
TitleBar();
}
} while (n != 0);
cout << CR << "System Stop";
return 0;
}
The common standard for terminals is the ANSI escape sequences. Based on the old common VT100 escape sequences I belive. I really would like SimpleIDE to support ANSI in it's terminal screen. But perhaps at that point it's more sensible to use a separate terminal program.
I really would like SimpleIDE to support ANSI in it's terminal screen. But perhaps at that point it's more sensible to use a separate terminal program.
Indeed. An ANSI terminal is pretty complicated, and providing UTF8 support makes it worse.
People who really need an ANSI terminal should use an existing program. The difficulty of that however lies in the multi-platform aspect that we're trying to honor. Issues are caused by using DTR for board reset; MAC does not honor stty settings (even as root!) and tends to change DTR to the opposite whatever the "last application" set - that and other things really turn me off about MAC. Propeller-load has an RTS reset option, but I've only tried that to make sure propeller can be programmed.
Below is a program that I put together to see how I would start to develop a C++ program. Of course it looks more like a plain C program at the moment. I decided to use the dreaded 'goto' just see if, and how it works. I also tried to implement a cin that would take in a string, just could not get that to work, maybe it's a limitation of tinystream? Basically:
string mystr;
getline(cin,mystr)
Using cin as an argument is new ground for me. I'm not sure that's the best idea. Is there a working example on the net?
Now, for the C++ experts, what functions could be converted into objects? I was thinking maybe the control of the pins? Somehow create an object with high(), low(), ..., etc?
A simple Pin class is a good example. Normally we organize a class as a collection of data and actions related to one "thing". If it's important enough, a thing can be extended into something else.
An object in C++ is an instance of a class, that is: Pin pin(number); creates an object of the class Pin.
It's best to use the term class when talking about code so other non-spin programmers understand.
This is out of a pdf tutorial that I am using. I have not tried this on a linux system yet, but all the other examples that were shown in the tutorial work.
Ray
<edit> Yes, I just tried this on my linux system using g++, it worked as expected. <edit>
// cin with strings
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string mystr;
cout << "What's your name? ";
getline (cin, mystr);
cout << "Hello " << mystr << ".\n";
cout << "What is your favorite team? ";
getline (cin, mystr);
cout << "I like " << mystr << " too!\n";
return 0;
}
Ok, so getline(..) is a library function. I suspect that tinystream is not implementing streams in a standard way, and that's why the program is failing. The tiny library is tiny because it is non-standard visa-vis. I seriously doubt that you will ever get file access working with tiny library streams.
The stdio parts of the tiny library do not offer file handle compatibility at all - fprintf(fp,"hello\n") will not work for example. This is explained in the distribution notes. I'll add similar notes for tiny streams.
That is a set back, just when I was starting to get the hang of cout/cin, and all the other things that come with iostream lib. I guess I will have to revert and do I/O using C style, and just maybe use cout as a replacement for printf(). If I look in the tinystream header file, will that list all of the functions that are available in the tinystream lib?
That is a set back, just when I was starting to get the hang of cout/cin, and all the other things that come with iostream lib. I guess I will have to revert and do I/O using C style, and just maybe use cout as a replacement for printf(). If I look in the tinystream header file, will that list all of the functions that are available in the tinystream lib?
Ray
You can use cin/cout as a printf replacement and use file io at the same time, but the solution will probably end up being bigger than just using standard C printf, fprintf, and friends. It may be possible to create some stream file IO classes that are more efficient though - wish i had more time to look at that.
Having more "embedded" classes like Pin and other hardware related things would be great. I've spent a little time thinking about that this morning since you've mentioned it, and hopefully I can post something to use later. I know that education has looked at this kind of thing, but they're not ready to publish yet until they are completely satisfied. We can talk about solutions here though.
Good start. A little suggestion. Given that you are going to create a pin object it might as well remember its own pin number. Then you don't need all those WCpin parameters. You can do this my giving the pin number to the objects constructor function.
Something like the outline below. I have also used "inline" to show how to get functions code to be place in line rather than using a call return.
class CPin {
public:
CPin (int pin); // Constructor, called when object is created.
void setInput();
void setOutput ();
void setHigh ();
void setLow ();
inline bool read();
private:
int mask;
};
// Constructor.
CPin::CPin (int pin) {
// Prepare a mask for this pin
mask = 1 << pin;
}
void CPin::setInput() {
DIRA &= ~mask;
}
void CPin::setOutput() {
DIRA |= mask;
}
void CPin::setHigh () {
OUTA |= mask;
}
void CPin::setLow () {
OUTA &= ~mask;
}
inline bool CPin::read () {
return (INA | mask);
}
/**
* Main program function.
**/
int main(void)
{
CPin pin(3);
pin.setOutput();
pin.setHigh();
return 0;
}
I see what you are getting at Heater.. I am more end product oriented, while you are more pin detail oriented, which makes a lot of sense. Something like what you proposed could be placed in a lib of its own? Also with your version you could add more pin manipulation functions, whatever that would be. With objects, I wonder if you could make a more sensible, to the average person, use of PASM, hidden within C++? It looks like this object stuff might have a lot of potential.
1) Move your class definition into it's own file cpin.h.
2) Move the main() function into it's own file cpin_test.cpp, say.
3) Add "#include "cpin.h" to both cpin.cpp and cpin_test.cpp
4) Compile cpin. cpp into an object file (as opposed to an executable)
$ gcc --static -c -o cpin.o cpin.cpp
Here "static" means this library code will be linked into your program rather than being dynamic shared library
"-c" means compile to object file, do not try to make an executable out of it.
"-o" is the output file name.
5. Then create an static library archive using the ar program:
$ ar rcs libcpin.a cpin.o
Here "r" is insert object into library. "c" is create library, "s" is "Write an object-file index into the archive" which is something of a mystery to me.
6. You can now compile your main() with the library to create your final executable.
$ gcc -o cpin cpin_test.cpp -L. -lcpin -lstdc++
The "-L" is the path to search for the library. If you put your libraries in some common directory you will want to change "." to your common directory path.
Note that libXXX.a is a unix convension for naming libraries, the .a indicating a static archive. You don't need the "lib" part or the ".a" in the -lcpin option above. Strange but true.
P.S. That inlining trick requires that the code to e inlined is actually written into the functions in the class definition in the header file.
For simple short methods like we have here you can get all the code to be compiled "inline" which saves the overhead of a call and return for just one line functional code. Then you have no object file to put in a library. I just tried it with a cpin header file like this:
class CPin {public:
inline CPin (int pin) {
// Prepare a mask for this pin
mask = 1 << pin;
}
inline void setInput() {
DIRA &= ~mask;
}
inline void setOutput () {
DIRA |= mask;
}
inline void setHigh () {
OUTA |= mask;
}
inline void setLow () {
OUTA &= ~mask;
}
inline bool read() {
return (INA | mask);
}
private:
int mask;
};
When compiling my little cpin_test.cpp I can get an assembly listing by using the -S switch and then see that the method calls are in fact turned into in line instructions.
With this kind of C++ functionality perhaps in line assembler is hardly ever required.
Below is a minimal version of the Heater. code, it works as expected. I wanted to try out a minimal first to make sure their were no problems with it working using <tinystream>.
This was an excellent example, Heater., with this idea, pin can be used in a whole bunch of different ways, not just limited to high/low like my example.
Ray
/**
* @file testBobject1.cpp
* This is the main testBobject1 program start point.
*/
#include <tinystream>
#include <propeller.h>
using namespace std;
class CPin {
public:
CPin(int pin);
void setOutput();
void setHigh();
void setLow();
private:
int mask;
};
CPin::CPin (int pin){
mask = 1 << pin;
}
void CPin::setOutput(){
DIRA |= mask;
}
void CPin::setHigh(){
OUTA |= mask;
}
void CPin::setLow(){
OUTA &= ~mask;
}
/**
* Main program function.
*/
int main(void)
{
CPin pin(16);
pin.setOutput();
pin.setHigh();
waitcnt(CLKFREQ/1+CNT);
pin.setLow();
return 0;
}
I decided to add the missing parts, and some comments. It compiled without error, I have not checked the read() function, I do not know how to add something like that to the example, and keep it simple.
Ray
/**
* @file testBobject1.cpp
* This is the main testBobject1 program start point.
*/
#include <tinystream>
#include <propeller.h>
using namespace std;
class CPin {
public:
CPin(int pin); /* Constructer, called when object is created. */
void setOutput(); /* Set pin up for output. */
void setInput(); /* Set pin up for input. */
void setHigh(); /* Set pin high. */
void setLow(); /* Set pin low. */
inline bool read(); /* Read pin data. ? */
private:
int mask;
};
CPin::CPin (int pin){
/* Prepare a mask for this pin. */
mask = 1 << pin;
}
void CPin::setInput(){
DIRA &= ~mask;
}
void CPin::setOutput(){
DIRA |= mask;
}
void CPin::setHigh(){
OUTA |= mask;
}
void CPin::setLow(){
OUTA &= ~mask;
}
inline bool CPin::read(){
return (INA | mask);
}
/**
* Main program function.
*/
int main(void)
{
CPin pin(16);
pin.setOutput();
pin.setHigh();
waitcnt(CLKFREQ/1+CNT);
pin.setLow();
return 0;
}
Pin classes are great Here's what I did yesterday.
Pin.h extends the P8x32aPin class. This is OOP in one sense but not another. Extending a class is OOPy, but the idea of having the Pin class extend the P8x32aPin class is a little backwards. I did it this way just to show that the Pin class can be anything, and this is a simple alternative to the more generic and code-bloating OOP method.
OOP programming tends to be more data driven than structured programming. To do it the OOPy way would require using virtual functions to make abstract classes. It would also require more code and reading information from some configuration. That is an exercise for the reader.
The high and low methods could have just as easily been implemented in the P8x32aPin "parent class". They were added to the Pin "child class" just to show some extension and hide some details. I suppose one could add in and out methods to Pin also.
/**
* @file P8x32aPin.h
*/
#include <propeller.h>
class P8x32aPin
{
public:
/* "default" class for arrays */
P8x32aPin() {
m_pin = 0;
}
/* class for single pins */
P8x32aPin(int number) {
m_pin = number;
}
/* pin number accessors */
void setPinNumber(int number) {
m_pin = number;
}
int getPinNumber() {
return m_pin;
}
/* pin directions */
void setDirection(bool output) {
if(output)
DIRA |= (1 << m_pin);
else
DIRA &= ~(1 << m_pin);
}
int getDirection() {
return DIRA & (1 << m_pin);
}
/* pin states */
void setState(int state) {
if(state)
OUTA |= (1 << m_pin);
else
OUTA &= ~(1 << m_pin);
}
int getState() {
return INA & (1 << m_pin) ? 1 : 0;
}
void toggleState() {
int state = INA & (1 << m_pin);
OUTA ^= (1 << m_pin);
}
private:
int m_pin;
};
Test program
/**
* @file PinClass.c
* This is the main PinClass program start point.
*/
#include "Pin.h"
/**
* Main program function.
*/
int main(void)
{
int m,n;
int low = 16; // first quickstart pin
int high = 19; // last pin for demo
/* use an array of 32 pins */
Pin pin [32];
for(n = 0; n < 32; n++) {
pin[n].setPinNumber(n);
}
for(n = low; n <= high; n++) {
/* set pins to output */
pin[n].setDirection(1);
}
for(m = 0; m < 4; m++) {
/* set pins high, then low */
for(n = low; n <= high; n++)
pin[n].high();
waitcnt(CLKFREQ/2+CNT);
for(n = low; n <= high; n++)
pin[n].low();
waitcnt(CLKFREQ/2+CNT);
}
while(true) {
/* toggle pins */
for(n = low; n <= high; n++)
pin[n].toggleState();
waitcnt(CLKFREQ/25+CNT);
}
return 0;
}
I guess this is a question for Dave Hein concerning filetest.c program. I was thinking about trying to make filetest work in C++, but I ran into some problems. Now, listed below, is a minimal code for filetest.c which I thought would be enough to get it started, or at least compile. I get errors, and I thought I had all of the necessary headers called. Hopefully you might have a clue as to what is going on.
Ray
Board Type - DNA:SQI; Compiler Type - C; Memory Model - CMM; Optimization - Os Size.
/**
* @file fileTcpp.cpp
* This is the main fileTcpp program start point.
*/
//#include <tinystream>
#include <propeller.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cog.h>
#include <sys/stat.h>
#include <dirent.h>
//#define CR '\n'
extern _Driver _SimpleSerialDriver;
extern _Driver _FileDriver;
_Driver *_driverlist[] = {
&_SimpleSerialDriver,
&_FileDriver,
NULL
};
char *FindChar(char *ptr, int val);
FILE *stdinfile;
FILE *stdoutfile;
//using namespace std;
/**
* Main program function.
*/
int main()
{
uint8_t buffer[80];
unsigned long n;
stdinfile = stdin;
stdoutfile = stdout;
buffer[0] = 0;
buffer[1] = 1;
buffer[2] = 2;
buffer[3] = 3;
LoadSDDriver(buffer);
dfs_mount();
waitcnt(CLKFREQ/6+CNT);
do
{
// cout << ">";
gets(buffer);
} while (n !=0);
// cout << CR << "System Stop";
return 0;
}
Most of the standard header files include the "extern "C" {" if __cplusplus is define, but sd.h does not have it. I have little experience with C++, but this might fix the problem.
Actually all those errors are from a C compile, I am not doing it in C++. I switched from a C++, to C .side, that is why I do not understand what is going on, I can not compile it in C.
Comments
SimpleIDE Console screen:
Hello World!
How old are you? 22
So, you are 22 years old.
Linux box:
Hello World!
How old are you? 22
So, you are 22 years old.
Why do I get the empty line in the Console screen?
Ray
Linux and Windows have inconsistent interpretations of New Line NL and Carriage Return CR.
I've allowed some options to handle this problem on the terminal.
By default "NL is Enter" is checked. Un-check it for this case.
In the Simple Terminal Options, you have (14) Position Cursor (x), and (15) Position Cursor (y). What would the command look like to implement these? I want to try to do some cursor placement in the Terminal window.
Ray
The Simple Terminal is supposed to be Parallax Serial Terminal (PST) compatible.
Some things like "Enter is NL", and "Swap Receive CR/NL" are provided to make it more generic.
There are differences between Windows and Linux/Unix that will never be resolved
The only reference that I know of is the Parallax Serial Terminal.spin object.
Guess that's the subject for another chapter in the SimpleIDE User Guide ....
Most of the PST commands require a single character like:
// home();
putchar(1); // send cursor home command
Three are a little more complicated:
// position(x,y)
putchar(2); // position x,y command
putchar(x);
putchar(y);
// position(x)
putchar(14); // position x command
putchar(x);
// position(y)
putchar(15); // position y command
putchar(y);
The putchar() works fine, for cursor placement, but I could not get it to work using cout. I tried cout << (14) << (9), but I just get bunch of strange numbers, and no cursor movement.
Ray
Now, for the C++ experts, what functions could be converted into objects? I was thinking maybe the control of the pins? Somehow create an object with high(), low(), ..., etc?
The settings for this are Board Type - Quickstart; Compiler Type - C++; Memory Model - CMM; Optimization - Os Size; Linker - Tiny Lib. Also, Enter is NL, unchecked, in the terminal options menu.
I also ran this program using Tera Term, and PuTTY, which did not run into any problems, of course the terminal screen control did not work. You would think their would be a standard for that by now.
What else? Oh Any ideas as to how I would test out reading and writing to an SD card, using <tinystream>? What are some options?
Ray
Indeed. An ANSI terminal is pretty complicated, and providing UTF8 support makes it worse.
People who really need an ANSI terminal should use an existing program. The difficulty of that however lies in the multi-platform aspect that we're trying to honor. Issues are caused by using DTR for board reset; MAC does not honor stty settings (even as root!) and tends to change DTR to the opposite whatever the "last application" set - that and other things really turn me off about MAC. Propeller-load has an RTS reset option, but I've only tried that to make sure propeller can be programmed.
#include <string> includes the C++ string class. #include <string.h> includes the normal C string library. They are different.
A simple Pin class is a good example. Normally we organize a class as a collection of data and actions related to one "thing". If it's important enough, a thing can be extended into something else.
An object in C++ is an instance of a class, that is: Pin pin(number); creates an object of the class Pin.
It's best to use the term class when talking about code so other non-spin programmers understand.
Ray
<edit> Yes, I just tried this on my linux system using g++, it worked as expected. <edit>
Page 32, in the version that I have.
http://www.cplusplus.com/doc/tutorial/
Ray
Ok, so getline(..) is a library function. I suspect that tinystream is not implementing streams in a standard way, and that's why the program is failing. The tiny library is tiny because it is non-standard visa-vis. I seriously doubt that you will ever get file access working with tiny library streams.
The stdio parts of the tiny library do not offer file handle compatibility at all - fprintf(fp,"hello\n") will not work for example. This is explained in the distribution notes. I'll add similar notes for tiny streams.
Thanks.
Ray
You can use cin/cout as a printf replacement and use file io at the same time, but the solution will probably end up being bigger than just using standard C printf, fprintf, and friends. It may be possible to create some stream file IO classes that are more efficient though - wish i had more time to look at that.
Having more "embedded" classes like Pin and other hardware related things would be great. I've spent a little time thinking about that this morning since you've mentioned it, and hopefully I can post something to use later. I know that education has looked at this kind of thing, but they're not ready to publish yet until they are completely satisfied. We can talk about solutions here though.
Ray
Good start. A little suggestion. Given that you are going to create a pin object it might as well remember its own pin number. Then you don't need all those WCpin parameters. You can do this my giving the pin number to the objects constructor function.
Something like the outline below. I have also used "inline" to show how to get functions code to be place in line rather than using a call return.
Ray
1) Move your class definition into it's own file cpin.h.
2) Move the main() function into it's own file cpin_test.cpp, say.
3) Add "#include "cpin.h" to both cpin.cpp and cpin_test.cpp
4) Compile cpin. cpp into an object file (as opposed to an executable)
Here "static" means this library code will be linked into your program rather than being dynamic shared library
"-c" means compile to object file, do not try to make an executable out of it.
"-o" is the output file name.
5. Then create an static library archive using the ar program: Here "r" is insert object into library. "c" is create library, "s" is "Write an object-file index into the archive" which is something of a mystery to me.
6. You can now compile your main() with the library to create your final executable. The "-L" is the path to search for the library. If you put your libraries in some common directory you will want to change "." to your common directory path.
Note that libXXX.a is a unix convension for naming libraries, the .a indicating a static archive. You don't need the "lib" part or the ".a" in the -lcpin option above. Strange but true.
P.S. That inlining trick requires that the code to e inlined is actually written into the functions in the class definition in the header file.
When compiling my little cpin_test.cpp I can get an assembly listing by using the -S switch and then see that the method calls are in fact turned into in line instructions.
With this kind of C++ functionality perhaps in line assembler is hardly ever required.
This was an excellent example, Heater., with this idea, pin can be used in a whole bunch of different ways, not just limited to high/low like my example.
Ray
Ray
Pin.h extends the P8x32aPin class. This is OOP in one sense but not another. Extending a class is OOPy, but the idea of having the Pin class extend the P8x32aPin class is a little backwards. I did it this way just to show that the Pin class can be anything, and this is a simple alternative to the more generic and code-bloating OOP method.
OOP programming tends to be more data driven than structured programming. To do it the OOPy way would require using virtual functions to make abstract classes. It would also require more code and reading information from some configuration. That is an exercise for the reader.
The high and low methods could have just as easily been implemented in the P8x32aPin "parent class". They were added to the Pin "child class" just to show some extension and hide some details. I suppose one could add in and out methods to Pin also.
Ray
Board Type - DNA:SQI; Compiler Type - C; Memory Model - CMM; Optimization - Os Size.
Build Status
Ray
Build Status
Ray