Shop OBEX P1 Docs P2 Docs Learn Events
P2 Smart pins serial TX and RX! — Parallax Forums

P2 Smart pins serial TX and RX!

Hi All,

Before I start this post, I know there are serial modules in Catalina that I can use to send and receive serial data on the Propeller 2. I have a special purpose for the serial UART/s and need to do things differently than the "standard" way. I set up the TX and RX smart pins like so from the examples I found:

uint32_t bitrate = 7 + ((_clockfreq()/baudrate) << 16);
_wrpin(txpin, 0x7C); // Set tx pin mode
_wxpin(txpin, bitrate); // Set tx bitrate
_dirh(txpin); // Enable txpin

_wrpin(rxpin, 0x3E); // Set rx pin mode
_wxpin(rxpin, bitrate); // Set rx bitrate
_dirh(rxpin); // Enable rxpin

I can transmit no problem using this:

_wypin(GRBL_TX, 'a');

Now the problem I have is receiving data with the smart pin and I am confused with how it works. I tried this as an example to see if the receive is working and it doesn't:

while(1) {
if (_rdpin(rxpin) == 'a') {
_wypin(txpin, 'X');
}
}

Am I missing something here? I noticed this in the P2 hardware manual:

RDPIN / RQPIN is used to read the received word. The word must be shifted right by 32 minus the word
size. For example, to LSB-justify an 8-bit word received, you would do a 'SHR D,#32-8'.

Can someone enlighten me here on how to do the _rdpin() function with the shift right by 32 in C? Forgive me for being ignorant but this stuff is new to me. Once I get the Rx data reading successfully I can move forward with what I'd like to do.

Thanks,

Eric

Comments

  • First off, you need to check before sending/receiving with the smart pins. On the TX side, you need to wait until the buffer is ready to receive a character, on the RX side you need to check if there's actually a new character in the buffer. In both cases, you need to check the IN register (where the non-smart input value would normally be).

    The right shift should be obvious: (unsigned)_rdpin(rxpin) >> 24

  • @Wuerfel_21 said:
    First off, you need to check before sending/receiving with the smart pins. On the TX side, you need to wait until the buffer is ready to receive a character, on the RX side you need to check if there's actually a new character in the buffer. In both cases, you need to check the IN register (where the non-smart input value would normally be).

    The right shift should be obvious: (unsigned)_rdpin(rxpin) >> 24

    Thank you for this :smile:

  • JonnyMacJonnyMac Posts: 9,158
    edited 2023-04-30 16:48

    This is in Spin, but does what you want. Per Ada's comment, you need to check the IN bit to see if anything is waiting first.

    pub rxcheck() : rxbyte 
    
    '' Check for serial input
    '' -- returns -1 if nothing available
    
      if (pinread(rxp)) 
        return rdpin(rxp) >> 24 
      else
        return -1
    

    Remember, the smart pin only has a 1-character buffer, so you need to make sure you're checking this very frequently to prevent overflow. This is typically done in a PASM cog.

  • @JonnyMac said:
    This is in Spin, but does what you want. Per Ada's comment, you need to check the IN bit to see if anything is waiting first.

    pub rxcheck() : rxbyte 
    
    '' Check for serial input
    '' -- returns -1 if nothing available
    
      if (pinread(rxp)) 
        return rdpin(rxp) >> 24 
      else
        return -1
    

    Remember, the smart pin only has a 1-character buffer, so you need to make sure you're checking this very frequently to prevent overflow. This is typically done in a PASM cog.

    Thank you very much Jon :smile:

  • evanhevanh Posts: 16,027
    edited 2023-05-01 02:11

    I devised a little trick for incoming key presses sent from typical modern PC terminal where there is known back-to-back triple byte groups. The basic idea is it reads 30 bits at a time (Assumes 8N1 framing) into the hardware buffer before the software examines anything. This lowers the polling needs considerably and allows lazy inline calls to the handler. No dedicated cog required.

    However, it relies on the sending hardware bunching the bytes tightly together without any extra spacing stop-bits between the bytes in the group. So it'll mess up if the sending hardware has timing gaps between bytes.

    My code used a pure pasm development environment where I could reserve a cogRAM register space. Eric adopted it into FlexC too. You could dig that code up I presume.

    '===============================================
    '  input:  (none)
    ' result:  Z flag, PB
    'scratch:  temp2
    '
    checkch
            testp   #DIAGRXPIN  wz      'word received in smartpin? (IN high == yes)
            rdpin   temp2, #DIAGRXPIN   'get data word from smartpin Z buffer
            shr temp2, #32-28       'shift the data to bottom of register
        _ret_   getbyte pb, temp2, #0       'fetch character from word
    
    
    '===============================================
    '  input:  (none)
    ' result:  PB
    'scratch:  temp2
    '
    getch
            testb   temp2, #8  wc       'framing stop-bit of prior character:  high= STOP
            testbn  temp2, #9  andc     'framing start-bit of next character:  low = START
            shr temp2, #10      'shift down next character, if any
    .loop1
        if_nc   testp   #DIAGRXPIN  wz      'word received in smartpin? (IN high == yes)
    if_nc_and_nz    jmp #.loop1         'if nothing recieved then wait
        if_nc   rdpin   temp2, #DIAGRXPIN   'get data word from smartpin Z buffer
        if_nc   shr temp2, #32-28       'shift the data to bottom of register
    
            getbyte pb, temp2, #0       'fetch character from word
            ret wcz         'restore C/Z flags of calling routine
    
Sign In or Register to comment.