Shop OBEX P1 Docs P2 Docs Learn Events
Process keyboard input — Parallax Forums

Process keyboard input

Hello!

I have this program that mostly works when using FlexProp with the internal PST terminal on MacOS. The only issue I have is with the comparison:

    cmp data_1, ##$0A wz 
    if_z jmp #.send_crlf

If I remove the if_z, then I get the correct output. If the "a" key is hit for example, it prints to the screen, is transfered to the buffer and then also prints that buffer. I'm not sure if I should be doing a comparison against the against the expected key (LF in this case on MacOS) or something else.

Full code:

' sets the system clock frequency
_CLKFREQ = 200_000_000
' set the receiving pin for input to the P2 microcontroller
RX_PIN = 63
' set the transmission pin for output from the P2 microcontroller
TX_PIN = 62
' set the baud mode to support 2000000 baud
BAUD_RATE = 2_000_000
' set the serial clock period for the baud rate based on the system clock frequency (_CLKFREQ)
SERIAL_CLOCK = ( _CLKFREQ / BAUD_RATE )
' calculate a bit period value for the serial communication baud rate.
BIT_PERIOD = (( SERIAL_CLOCK << 16 ) & $FFFFFC00 ) + ( 32 - 1 )

dat
    org       0   ' start assembling code from address 0
    asmclk     ' use the system clock (_CLKFREQ) for timing-related calculations 

    ' Configure RX smart pin
    wrpin    ##(P_ASYNC_RX | P_HIGH_15K ), #RX_PIN  ' configure the RX pin as a smart pin for asynchronous serial reception
    wxpin    ##BIT_PERIOD, #RX_PIN             ' set the correct timing for receiving bits at the correct speed
    dirh     #RX_PIN                           ' sets the direction of the RX pin to high

    ' Configure TX smart pin
    wrpin    ##(P_ASYNC_TX | P_OE), #TX_PIN    ' configure the TX pin as a smart pin for asynchronous serial transmission 
    wxpin    ##BIT_PERIOD, #TX_PIN             ' set the correct timing for transmitting bits at the correct speed
    dirh     #TX_PIN                           ' sets the direction of the TX pin to high

    ' Initialize buffer and pointers
    mov buf_ptr, #input_buffer  ' Initialize buffer pointer

.process_key
.get_key 
    testp #RX_PIN wc          ' test the state of RX_PIN and update the carry flag
    if_nc jmp #.get_key       ' Wait until a key is pressed
    rdpin data_1, #RX_PIN     ' Read received byte/keypress

    ' Echo the received byte back to the terminal
    wypin data_1, #TX_PIN      ' Echo received byte/keypress immediately

.send_key 
    ' Store the received byte in the buffer
    wrbyte data_1, buf_ptr
    add buf_ptr, #1            ' Move buffer pointer to next position


    cmp data_1, ##$0A wz  
    if_z jmp #.send_crlf


    jmp #.process_key          ' Process more keys

.send_crlf     
    ' Send LF (0x0A)
    mov data_1, ##$0A
    wypin data_1, #TX_PIN
    waitx ##5000

    ' Null-terminate the buffer
    wrbyte #0, buf_ptr

    ' Print the buffer
    mov print_ptr, #input_buffer
    call #print_buffer

    ' Reset buffer pointer
    mov buf_ptr, #input_buffer

    jmp #.process_key

' Print Buffer Subroutine (Simplified)
print_buffer
    ' Start reading buffer
    mov print_ptr, #input_buffer    ' Initialize the print pointer

.loop_print
    rdbyte data_2, print_ptr        ' Read the byte from the buffer
    cmps data_2, #0 wz              ' Check if it's a null terminator (0x00)
    if_z jmp #.end_print            ' If null terminator, end printing

    ' Echo the character back (print it)
    wypin data_2, #TX_PIN           ' Send the character via TX

    ' Move pointer to next byte
    add print_ptr, #1
    jmp #.loop_print                 ' Loop to print next byte

.end_print
    ret

' Reserve space in memory for variables/data
data_1   res 1
data_2   res 1
tmp      res 1
debug_char res 1 ' Reserved space for debugging
line_num res 1  ' Stores the current line number
col_num  res 1  ' Stores the current column number

' Reserve space for input buffer (32 bytes)
input_buffer  res 32
buf_ptr       res 1    ' Buffer pointer
print_ptr     res 1  ' Pointer used for printing the buffer

Comments

  • evanhevanh Posts: 16,334
    edited 2025-02-25 23:29

    Chances are that what is typed is correct for printing also. ie: Don't need an end of line check for printing typed text.

    PS: Printing the hex codes of each character might help you understand any confusion. That way you get to see all the non-printables.

  • Hi @evanh

    Correct, it is printing and going to the newline via line (at least for the PST terminal). I still just want to capture the newline and examine it.

    I'll give the hex printing a shot! I have some code that I can take from the double dabble code I had in another thread. I just think I need to figure out what shr I need to do at this point for the high/low nibbles. Thank you!

  • proppyproppy Posts: 22
    edited 2025-02-27 21:19

    I tried the hex stuff. Seems to be a little off though. I changed it up abit to see if could get the ascii to print. If data_1 comes in from rdpin then print seems to out put -u1. However, if I use a a mov temp, #"a" for the direct assignment I get the expected 61 as output. So, it must be something with

    Something with the initial pin setup.
    Something with data_1 either when doing rdpin data_1, #RX_PIN
    Something with converting ASCII coming from the keyboard.

  • Hi,
    Do you really want to receive 32bit codes instead of 8 bit chars?
    You might want to Check the
    Wxpin. Statement.
    Cheers Christof

  • @"Christof Eb." said:
    Hi,
    Do you really want to receive 32bit codes instead of 8 bit chars?
    You might want to Check the
    Wxpin. Statement.
    Cheers Christof

    Wow, this was it. The printing worked because rdpin reads the full 32bits regardless from what i can tell, but all the code after that went haywire. Doing 8 bits makes it simpler to get the lower 8 bits, which is all i need. I think i solved it but cleaning up the code a bit before reposting solution.

  • proppyproppy Posts: 22
    edited 2025-03-01 13:10

    I think i got it working. It could probably use some improvement or optimization though.

    I had to change this

    BIT_PERIOD = (( SERIAL_CLOCK << 16 ) & $FFFFFC00 ) + ( 32 - 1 )
    

    to this

    BIT_PERIOD = (( SERIAL_CLOCK << 16 ) & $FFFFFC00 ) + ( 8 - 1 )
    

    Afterwards though I had to get the lower 8 bits, pretty sure the higher ones probably contain garbage i didn't need.

        shr    data_1, #24           ' Extract the received byte
        and    data_1, #$FF          ' Ensure only the lower 8 bits are used
    

    I noticed that printing the buffer was only printing two characters so I added a short delay inside the loop:

        rdbyte data, print_ptr        ' Read a byte
        cmp data, #0 wz               ' Check if it's null terminator
        if_z jmp #.end_print            ' If null, stop
    
        wypin data, #TX_PIN           ' Print character
        waitx ##5000                    ' Short delay to see the output
    

    The final result is listed here:

    ' sets the system clock frequency
    _CLKFREQ = 200_000_000
    ' set the receiving pin for input to the P2 microcontroller
    RX_PIN = 63
    ' set the transmission pin for output from the P2 microcontroller
    TX_PIN = 62
    ' set the baud mode to support 2000000 baud
    BAUD_RATE = 2_000_000
    ' set the serial clock period for the baud rate based on the system clock frequency (_CLKFREQ)
    SERIAL_CLOCK = ( _CLKFREQ / BAUD_RATE )
    ' calculate a bit period value for the serial communication baud rate.
    BIT_PERIOD = (( SERIAL_CLOCK << 16 ) & $FFFFFC00 ) + ( 8 - 1 )
    
    dat
        org       0   ' start assembling code from address 0
        asmclk     ' use the system clock (_CLKFREQ) for timing-related calculations 
    
        ' Configure RX smart pin
        wrpin    ##(P_ASYNC_RX | P_HIGH_15K), #RX_PIN  ' configure the RX pin as a smart pin for asynchronous serial reception
        wxpin    ##BIT_PERIOD, #RX_PIN             ' set the correct timing for receiving bits at the correct speed
        wypin    #1, #RX_PIN                      ' Enable the smart pin
        dirh     #RX_PIN                          ' sets the direction of the RX pin to high
    
        ' Configure TX smart pin
        wrpin    ##(P_ASYNC_TX | P_OE), #TX_PIN    ' configure the TX pin as a smart pin for asynchronous serial transmission 
        wxpin    ##BIT_PERIOD, #TX_PIN             ' set the correct timing for transmitting bits at the correct speed
        wypin    #1, #TX_PIN                      ' Enable the smart pin transmitter
        dirh     #TX_PIN                          ' sets the direction of the TX pin to high
    
        mov buf_ptr, #input_buffer  ' Initialize buffer pointer
    
    .process_key
    .get_key 
        testp #RX_PIN wc        ' Check if data is ready on RX_PIN
        if_nc jmp #.get_key     ' Wait until a key is pressed
    
        rdpin data, #RX_PIN         ' Read received byte
        shr    data, #24            ' Extract the received byte
        and    data, #$FF           ' Ensure only the lower 8 bits are used
    
        wypin data, #TX_PIN         ' Echo the received character
    
        wrbyte data, buf_ptr        ' Store the received byte in the buffer
        add buf_ptr, #1     ' Move buffer pointer to next position
    
    .send_key     
        cmp data, ##$0D wz      ' Test if data equals 'CR' (carriage return)
        if_z jmp #.send_crlf        ' If 'CR' is pressed, process the buffer
    
        jmp #.process_key       ' Continue to process more keys
    
    .send_crlf      
        wypin ##$0A, #TX_PIN        ' Send LF (0x0A) in order to go to the next line
    
        wrbyte #0, buf_ptr      ' Null-terminate the buffer
    
        call #.print_buffer     ' Print the buffer content
    
        mov buf_ptr, #input_buffer  ' Reset buffer pointer
    
        jmp #.process_key       ' Return to processing more keys
    
    .print_buffer
        mov print_ptr, #input_buffer    ' Start at the beginning
    
    .loop_print
        rdbyte data, print_ptr  ' Read a byte
        cmp data, #0 wz     ' Check if it's null terminator
        if_z jmp #.end_print        ' If null, stop
    
        wypin data, #TX_PIN     ' Print character
        waitx ##5000            ' Short delay to see the output
    
        add print_ptr, #1       ' Move to next character
        jmp #.loop_print
    
    .end_print
        ret
    
    ' Reserve space in memory for variables/data
    data        res 1
    input_buffer    res 1       ' Reserve space for input buffer (32 bytes)
    buf_ptr     res 1       ' Buffer pointer
    print_ptr   res 1       ' Pointer used for printing the buffer
    

    It works fine in PST terminal but not in the ANSI terminal. I'm still using FlexProp for MacOS. I may look into this later to see what needs to be done for ANSI terminal.

    Thanks @evanh and @"Christof Eb."!

    EDIT: I just realized I need to use the escape codes for the built in ANSI terminal. :D

Sign In or Register to comment.