Propeller C - high() or low() changes direction, and input() function not recognized?

Hi,

I've been experimenting with SimpleIDE to toggle some pins. What I noticed is that high() or low() set the pins to outputs, which is unsafe if they were inputs and a mistake was made. Also, the input() function is not recognized. I'm including simpletools.h.

What I propose is a change of paradigm, as used in other micro-controllers:
//Fuction prototypes
_Bool getlat(unsigned char)
_Bool getpin(unsigned char)
void setpin(unsigned char, _Bool)
void togpin(unsigned char)

_Bool getlat(unsigned char pin)  // Gets the value written to the output latch of the pin
{
    return (_OUTA & 1 << pin) != 0;
}

_Bool getpin(unsigned char pin)  // Gets the value at the pin
{
    return (_INA & 1 << pin) != 0;
}

void setpin(unsigned char pin, _Bool val)  // Sets the output pin to the given value
{
    if (val != getlat(pin))  // Notice that we are comparing to the latch, not actually reading from the pin
        togpin(pin); 
}

void togpin(unsigned char pin)  // Toggles the output pin
{
    _OUTA ^= 1 << pin;
}

This code wasn't thoroughly tested, but it should work. The idea is that one should set the pin direction previously, and explicitly, before using them. Although usually used on input pins, getpin() makes sense if used on output pins, if we want to see if the pin is not shorted.

Comments

  • @samuell,

    I'm 100% with you on your opinion here. However, the author of the Simple libraries was perfectly aware what he was doing, and surely meant to write the functions exactly as they are written. I believe the choice was between simplicity and flexibility, and he went with simplicity. So much of Parallax's revenue comes from education (and that is the primary goal of SimpleIDE and the Simple libraries) that simplicity outweighed the consequences you outline above.
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
    CI Server: https://ci.zemon.name?guest=1
  • In the SimpleIDE library v 0.98.1 there are the following functions related to pin I/O. There is an input() function as well as functions to set the direction of a pin or a group of pins. I did try to use the input() function and it did work.

    Note sometimes for intercog communication I use the get_state() function for one cog to read the output pin state set by another cog.

    Tom

    void 	high (int pin)
     	Set an I/O pin to output-high.
    void 	low (int pin)
     	Set an I/O pin to output-low.
    int 	input (int pin)
     	Set an I/O pin to input and return 1 if pin detects a high signal, or 0 if it detects low.
    
    More Individual I/O
    unsigned int 	toggle (int pin)
     	Toggle the output state of the I/O pin.
    unsigned int 	reverse (int pin)
     	Reverse the direction of an I/O pin.
    unsigned int 	get_state (int pin)
     	Check the state of an I/O pin without setting it to input.
    unsigned int 	get_direction (int pin)
     	Check the direction of the I/O pin.
    unsigned int 	get_output (int pin)
     	Get I/O pin output state.
    void 	set_direction (int pin, int direction)
     	Set an I/O pin to a given direction.
    void 	set_output (int pin, int state)
     	Set I/O pin output register bit to either 1 or 0.
    
    Group I/O
    unsigned int 	get_states (int endPin, int startPin)
     	Get states of a contiguous group of I/O pins.
    unsigned int 	get_directions (int endPin, int startPin)
     	Get directions for a contiguous group of I/O pins.
    unsigned int 	get_outputs (int endPin, int startPin)
     	Get output settings for a contiguous group of I/O pins.
    void 	set_directions (int endPin, int startPin, unsigned int pattern)
     	Set directions for a contiguous group of I/O pins.
    void 	set_outputs (int endPin, int startPin, unsigned int pattern)
     	Set output states for a contiguous group of I/O pins. 
    
    
  • DavidZemon wrote: »
    @samuell,

    I'm 100% with you on your opinion here. However, the author of the Simple libraries was perfectly aware what he was doing, and surely meant to write the functions exactly as they are written. I believe the choice was between simplicity and flexibility, and he went with simplicity. So much of Parallax's revenue comes from education (and that is the primary goal of SimpleIDE and the Simple libraries) that simplicity outweighed the consequences you outline above.
    Yup, there is a reason for that decision, and I think the motive behind it would be something in that order. However, I wouldn't use that implementation for commercial projects, as it is seriously unsafe. I don't say my approach is better either, since there might be a simpler implementation of setpin(), without recurring to other functions.

    As for the simplicity motive, it might lock people to a mindset. I see it happening with Arduino. It happened myself when I refused to learn C/C++ due to the simplicity of Euphoria.
  • samuellsamuell Posts: 365
    edited 2016-06-09 - 13:39:52
    twm47099 wrote: »
    In the SimpleIDE library v 0.98.1 there are the following functions related to pin I/O. There is an input() function as well as functions to set the direction of a pin or a group of pins. I did try to use the input() function and it did work.

    Note sometimes for intercog communication I use the get_state() function for one cog to read the output pin state set by another cog.

    Tom

    void 	high (int pin)
     	Set an I/O pin to output-high.
    void 	low (int pin)
     	Set an I/O pin to output-low.
    int 	input (int pin)
     	Set an I/O pin to input and return 1 if pin detects a high signal, or 0 if it detects low.
    
    More Individual I/O
    unsigned int 	toggle (int pin)
     	Toggle the output state of the I/O pin.
    unsigned int 	reverse (int pin)
     	Reverse the direction of an I/O pin.
    unsigned int 	get_state (int pin)
     	Check the state of an I/O pin without setting it to input.
    unsigned int 	get_direction (int pin)
     	Check the direction of the I/O pin.
    unsigned int 	get_output (int pin)
     	Get I/O pin output state.
    void 	set_direction (int pin, int direction)
     	Set an I/O pin to a given direction.
    void 	set_output (int pin, int state)
     	Set I/O pin output register bit to either 1 or 0.
    
    Group I/O
    unsigned int 	get_states (int endPin, int startPin)
     	Get states of a contiguous group of I/O pins.
    unsigned int 	get_directions (int endPin, int startPin)
     	Get directions for a contiguous group of I/O pins.
    unsigned int 	get_outputs (int endPin, int startPin)
     	Get output settings for a contiguous group of I/O pins.
    void 	set_directions (int endPin, int startPin, unsigned int pattern)
     	Set directions for a contiguous group of I/O pins.
    void 	set_outputs (int endPin, int startPin, unsigned int pattern)
     	Set output states for a contiguous group of I/O pins. 
    
    
    Hi Tom, I have to check which version I'm using. All I know is that input() is not recognized. Normally I tend to go with the existing library functions. Also, I like to set the direction initially, within my usual init() routine, and not having high() or low() setting the direction for me. Also, using high() or low() implies that:
    if (condition == true)
        high(pin);
    else
        low(pin);
    
    instead of just
    set_output(condition == true);
    
    It is unnecessary to use two separate functions for the same thing with different values, IMHO. But two extra functions won't hurt either.

    By the way, the get_state() and get_states() functions read from _INA or from _OUTA? One thing is reading from the actual pin, other is reading from the output latch. If the output pin is forced the values might not match. Conversely get_output() and get_outputs() use what register? Also, does set_output() and set_outputs() set the direction to outputs? There is no documentation regarding these specificities. In the end, I could have used those functions, but the lack of documentation was what lead me to create the alternatives, because I didn't even knew about them, and yet I'm to learn about the specifics. Sorry, but such lack of documentation is appalling.

    All other standard C functions were not a problem to me, because I can use other sources. I already had such conundrum when wanting to use lockset(), locknew(), lockclr() and cogstart(). Names are not intuitive and documentation is not very clear. Same as for these, because one has an hart time to understand what reads from the pins (e.g. _INA) and what reads from the latch (e.g. _OUTA). Proper naming is advised. My suggestion:
    - Keyword "input" only if the function sets the direction to input;
    - Keyword "output" only if the function sets the direction to output;
    - Keyword "pin" if the function reads from the pins (but OK if it writes to the latch);
    - Keyword "latch" if the function reads from the output latch.

    As for having to create custom functions when I probably didn't have to, oh well, at least my little test program is compatible with any lib version.

    Kind regards, Samuel Lourenço
  • samuell wrote: »
    However, I wouldn't use that implementation for commercial projects, as it is seriously unsafe.

    And Parallax does not recommend SimpleIDE or the Simple libraries for production use :(

    However, you may enjoy PropWare if you're willing to give C++ a shot. I developed it with more complicated programs in mind, and where you need better flexibility. The Pin class has a few different constructors, one of them takes a pin mask and direction.
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
    CI Server: https://ci.zemon.name?guest=1
  • DavidZemon wrote: »
    samuell wrote: »
    However, I wouldn't use that implementation for commercial projects, as it is seriously unsafe.

    And Parallax does not recommend SimpleIDE or the Simple libraries for production use :(

    However, you may enjoy PropWare if you're willing to give C++ a shot. I developed it with more complicated programs in mind, and where you need better flexibility. The Pin class has a few different constructors, one of them takes a pin mask and direction.
    Thanks, David! I guess that it is an option.

    Kind regards, Samuel Lourenço
  • samuell wrote: »
    Hi Tom, I have to check which version I'm using. All I know is that input() is not recognized. Normally I tend to go with the existing library functions.

    The Simpletools library version I mentioned is the latest.

    By the way, the get_state() and get_states() functions read from _INA or from _OUTA?

    Not sure if this helps, but this is what the library says:
     It tells you the actual state of each pin, regardless of whether it's a voltage applied to input or transmitted by an output.
    
    
    Conversely get_output() and get_outputs() use what register? Also, does set_output() and set_outputs() set the direction to outputs?

    The function takes 2 parameters:
    void set_output 	( 	int  	pin,
    		int  	state 
    	) 		
    
    Set I/O pin output register bit to either 1 or 0.
    
    This function focuses on the I/O pin's output register. If you intend to use it to send
     high or low signals, consider using high or low functions. This function can also be 
    used in conjunction with set_direction to send high or low signals.
    
    Parameters
        pin	I/O pin to set high or low.
        state	1 for high, 0 for low (when pin is actually set to output, which can be done with setDirection. 
    
    

    All other standard C functions were not a problem to me, because I can use other sources. I already had such conundrum when wanting to use lockset(), locknew(), lockclr() and cogstart(). Names are not intuitive and documentation is not very clear. Same as for these, because one has an hart time to understand what reads from the pins (e.g. _INA) and what reads from the latch (e.g. _OUTA). Proper naming is advised. My suggestion:
    - Keyword "input" only if the function sets the direction to input;
    - Keyword "output" only if the function sets the direction to output;
    - Keyword "pin" if the function reads from the pins (but OK if it writes to the latch);
    - Keyword "latch" if the function reads from the output latch.

    As for having to create custom functions when I probably didn't have to, oh well, at least my little test program is compatible with any lib version.

    Kind regards, Samuel Lourenço

    lockset and the other functions/defines are in the propeller.h library. The documentation is terse, and it would be more useful if it was expanded. The propeller.h library is a lower level library and the functions/defines are essentially analogous to the commands/registers in Spin. For example the dira define is used to load the dira register for the cog with the 32 bit mask. (DIRA = int IO_direction_pin_mask;). The biggest problem I had when using these was understanding how to use the register aliases. Once I read up on them in the propeller manual it became clearer. So yes some more detailed documentation (or at least pointers to other documentation would be very useful, particularly since the propeller.h functions/registers work faster than the Simpletools versions.

    Tom
Sign In or Register to comment.