Shop OBEX P1 Docs P2 Docs Learn Events
serial.h versus fdserial.h along with simpletext.h — Parallax Forums

serial.h versus fdserial.h along with simpletext.h

LoopyBytelooseLoopyByteloose Posts: 12,537
edited 2014-05-20 20:32 in Propeller 1
Okay, I can comprehend simpletext is supposed to offer terminal serial services in the Propeller, but it appears to require serial.h and/or fdserial.h

I am quite confused as how to swap a half-duplex serial configuration for a full-duplex serial configuration.

I have lookked at the library documentation but it appears to be robotically generated text without any clairty of the pros and cons or what might be the pitfalls in switching between the to. My gut feeling in general is to always use full-duplex. But then I see language that refers to 'blocking' and 'non-block' code and begin to wonder if full-duplex is really what it should be.

Maybe this is just a way of suggesting that a LEARN tutorial should sort this out. I get a bit tangled up as I am trying to port Arduino code that seems to always be half-duplex into Propeller code that I desire to be full-duplex. (And my reasons for doing so might not be well-founded).

Comments

  • jazzedjazzed Posts: 11,803
    edited 2014-05-16 07:53
    The default is serial.h. You don't have to think about that.

    If you want to use fdserial.h there are two approaches. Use write*(fdser,foo) or reassign the default device.

    These are shown in the libfdserial and libsimpletext examples.

    We have added a simpleterm_set(ptr) function to reassign the default device. That may not be in your Learn package yet. This is the definition:
    static inline void simpleterm_set(text_t *ptr)
    {
      extern text_t *dport_ptr;
      simpleterm_close();
      dport_ptr = ptr;
    }
    


    To use that, all you have to do is something like simpleterm_set(fdserial_open(31,30,0,115200));
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2014-05-16 09:06
    @Jazzed
    Thanks, so far the hardest part of learning GCC is knowing how to ask an intelligent question.
  • pmrobertpmrobert Posts: 673
    edited 2014-05-16 10:02
    I'm accessing the serial port quickly, reliably and without drama using this scheme:
    #include "simpletools.h"    // Include simpletools library 
    #include "fdserial.h"       // Include Full Duplex Serial library
    ...
    fdserial *serial = fdserial_open(31,30,0,250000);
    ...
     while(1) 
          {            
            fdserial_rxFlush(serial);            
            c = fdserial_rxChar(serial);  
                
            
            switch (c) 
            {          
    ...
    
    

    It doesn't appear to consume much memory either but I'm wondering if there's a better way to do full duplex serial. Oh, the 250000 baud rate is not a typo - there's a reason for it.

    -Mike
  • jazzedjazzed Posts: 11,803
    edited 2014-05-16 10:22
    Alternatively.
    #include "simpletools.h"    // Include simpletools library 
    #include "fdserial.h"       // Include Full Duplex Serial library
    ...
    fdserial *serial = fdserial_open(31,30,0,250000);
    ...
     while(1) 
          {            
            c = readChar(serial);  
                
            
            switch (c) 
            {          
    ...
    
    


    Of course the fdserial_* specific utilities are still available ... you can even write your own.

    One alternative to fdserial_* is to make a variation with smaller PASM code. The fdserial library actually uses the Parallax Serial Terminal.spin pasm pst.spin which has 64byte transmit and receive buffers. The buffer length can be adjusted by rebuilding libfdserial.
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2014-05-18 02:08
    Thanks, I am considering using a full duplex with XON/XOFF flow control. In that context, the input buffer would have to generate an XOFF when roughly 3/4th full, and the output buffer might be completely eliminated so that XOFF and XON response would be fast.

    Does the fdserial use more code space that the default? I can't seem to see a good reason to have half-duplex be the default and full-duplex be the alternative.
  • jazzedjazzed Posts: 11,803
    edited 2014-05-18 08:34
    Does the fdserial use more code space that the default?

    Yes.

    None of these drivers were written to have flow control.
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2014-05-19 08:07
    Okay, I understand that fdserial.h requires more code space than serial.h
    And I understand that neither hardware or software flow control is implemented.

    I am wondering about another aspect... serial.h is the default serial interface. Does that mean that it is NOT necessary to explicitly include the serial.h library at the beginning of a project?

    Or is it necessary to always include all the libraries required at the beginning of a project.

    In my instance, fdserial.h was included, not serial.h. But it seems that the code is calling half-duplex serial via the Propelleruino library.
  • pmrobertpmrobert Posts: 673
    edited 2014-05-19 10:27
    Another related question - I seem to recall that fdserial runs in it's own cog but the standard serial.h does not - Is that correct? Also, is there a standard way to check cog usage? I think the math libs can use either no, 1 or 2 cogs or am I confusing the GCC libs with Catalina?
  • jazzedjazzed Posts: 11,803
    edited 2014-05-19 10:51
    I am wondering about another aspect... serial.h is the default serial interface. Does that mean that it is NOT necessary to explicitly include the serial.h library at the beginning of a project?

    Or is it necessary to always include all the libraries required at the beginning of a project.


    All that is required is to include something that includes serial.h such as simpletools.h or simpletext.h

    In my instance, fdserial.h was included, not serial.h. But it seems that the code is calling half-duplex serial via the Propelleruino library.


    Yes, by default serial.h is used by default unless code is added to change that to fdserial.h


    @pmrobert,

    Yes fdserial.h uses it's own cog.
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2014-05-19 11:15
    Thanks.
    The Propelleruino library defaults to using the fdserial, but calls are in the Arduino language as Serial. That has been the source of confusion on my part.

    Since I seem to be shut out of the serial port on either input or output at different times in my project's code, it was important to run down whether the full-duplex or half-duplex context was in use. Just reading the code superficially seemed to indicate half-duplex. But it is just the opposite.
  • KyeKye Posts: 2,200
    edited 2014-05-19 18:39
    I need to mimick the behavior of Arduino Serial.begin(baudRate) and Serial.end() in a library I'm porting to the Propeller.

    So far I have:
    inline void serialBegin()
    {
        #ifdef ARDUINO
        {
            Serial.begin(DEF_BAUD_RATE);
        }
        #elif defined __PROPELLER__
        {
            extern text_t *dport_ptr;
            simpleterm_close();
            dport_ptr = fdserial_open(31, 30, 0, DEF_BAUD_RATE);
        }
        #endif
    }
    
    
    inline void serialEnd()
    {
        #ifdef ARDUINO
        {
            Serial.end();
        }
        #elif defined __PROPELLER__
        {
            simpleterm_close();
        }
        #endif
    }
    

    Does that seem correct? I also need to set the baud rate too dynamically. How would I do that? And... can I change the serial pins manually before I start the driver if the simpleSerial driver is running? I think I can.
  • jazzedjazzed Posts: 11,803
    edited 2014-05-19 20:02
    Hi Kye,

    Look at this: http://forums.parallax.com/attachment.php?attachmentid=108093&d=1397242664

    I think the basics are already done for Serial.h, but any improvements are welcome.


    Kye wrote: »
    I need to mimick the behavior of Arduino Serial.begin(baudRate) and Serial.end() in a library I'm porting to the Propeller.

    So far I have:
    inline void serialBegin()
    {
        #ifdef ARDUINO
        {
            Serial.begin(DEF_BAUD_RATE);
        }
        #elif defined __PROPELLER__
        {
            extern text_t *dport_ptr;
            simpleterm_close();
            dport_ptr = fdserial_open(31, 30, 0, DEF_BAUD_RATE);
        }
        #endif
    }
    
    
    inline void serialEnd()
    {
        #ifdef ARDUINO
        {
            Serial.end();
        }
        #elif defined __PROPELLER__
        {
            simpleterm_close();
        }
        #endif
    }
    

    Does that seem correct? I also need to set the baud rate too dynamically. How would I do that? And... can I change the serial pins manually before I start the driver if the simpleSerial driver is running? I think I can.
  • KyeKye Posts: 2,200
    edited 2014-05-19 20:08
    I got everything working.

    Thanks,
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2014-05-19 23:48
    AT this point, I just need to learn the fdserial.h interface. Obviously it works, but the ported code I am using is not working with it. I guess I will work with some fdserial examples independent of the project. Like a loop-back, or a menu of items to respond to.
  • KyeKye Posts: 2,200
    edited 2014-05-20 20:32
    @Jazzed

    I need to call simpleterm_close() once and only once before main from an included library header file. I tried doing this:
        __attribute__((constructor))
        void PropellerConstructor(void) 
        {
            simpleterm_close();    
        }
    

    But it doesn't get called even though the function is in a header file include by the main.c file (nor if I put it directly in the main.c file). Any thoughts on how to do this?

    ...

    I have to close the simpleterm to switch it out for fullduplex instead. This is why I need to do this. I have to make sure simpleterm_close() is not called twice because the code for it always casts the dport_ptr as a simple term and tries to close it even if fullduplex has been switched in instead. This means I have to make sure this function only runs once. I'd rather not add a function the user has to call to get this working. The library I am porting over has no way to call the simpleterm_close() function only once without adding an extra function the user has to call (this is because the library is header only, it doesn't have static vars to keep state, just objects which aren't unique).

    EDIT: It looks like the issue is the order by which constructors are called... Since priority constructors are called before non-priority constructors (simpleterm_open begin non-priority) I guess I can't do this trick.
Sign In or Register to comment.