Shop OBEX P1 Docs P2 Docs Learn Events
receiving serial data with smartpins — Parallax Forums

receiving serial data with smartpins

I'm trying to write a serial object for the P2 Eval board that uses smart pins instead of bitbanging DIRB, and I can get the transmit to work fine but I've done something stupid on receive. Could someone do a sanity check on my setup? I tried to base it on the ROM and the smartpin_serial_turnaround.spin2 demo file.

The code is below. As I mentioned, serial transmit works, so the clock setup and baud calculation are presumably correct. And I see the small LED next to the USB input flicker when I type characters in the terminal window, so I think the Windows terminal program is working (it is definitely receiving correctly, since I see the initial prompt).

The serial code:
'
' simple smart pin serial object for P2 Eval board
'
CON
  _txmode       = %0000_0000_000_0000000000000_01_11110_0 'async tx mode, output enabled for smart output
  _rxmode       = %0000_0000_000_0000000000000_00_11111_0 'async rx mode, input  enabled for smart input

VAR
  long rx_pin, tx_pin

PUB start(rxpin, txpin, mode, baudrate) | bitperiod, txmode, rxmode
  bitperiod := 7 + ((CLKFREQ / baudrate) << 16)
  rx_pin := rxpin
  tx_pin := txpin
  txmode := _txmode
  rxmode := _rxmode
  asm
    wrpin txmode, txpin
    wxpin bitperiod, txpin
    dirh  txpin
    wrpin rxmode, rxpin
    wxpin bitperiod, rxpin
    dirl  rxpin
  endasm
  return 1
  
PUB tx(val) | txpin, z
  txpin := tx_pin
  asm
    wypin val, txpin
    waitx #1
  endasm
  z := 1
  repeat while z <> 0
    asm
      testp txpin wc
   if_c mov z, #0
    endasm

' check if byte received (never waits)
' returns -1 if no byte, otherwise byte

PUB rxcheck : rxbyte | rxpin, z
  rxbyte := -1
  rxpin := rx_pin
  asm
    testp rxpin wc  ' char ready?
    if_c rdpin rxbyte, rxpin
    if_c shr rxbyte, #24
  endasm

' receive a byte (waits until one ready)
PUB rx : v
  repeat
    v := rxcheck
  while v == -1

' transmit a string
PUB str(s) | c
  REPEAT WHILE ((c := byte[s++]) <> 0)
    tx(c)

PUB dec(value) | i, x

'' Print a decimal number
  result := 0
  x := value == NEGX                                                            'Check for max negative
  if value < 0
    value := ||(value+x)                                                        'If negative, make positive; adjust for max negative
    tx("-")                                                                     'and output sign

  i := 1_000_000_000                                                            'Initialize divisor

  repeat 10                                                                     'Loop for 10 digits
    if value => i                                                               
      tx(value / i + "0" + x*(i == 1))                                          'If non-zero digit, output digit; adjust for max negative
      value //= i                                                               'and digit from value
      result~~                                                                  'flag non-zero found
    elseif result or i == 1
      tx("0")                                                                   'If zero digit (or only digit) output it
    i /= 10                                                                     'Update divisor

PUB hex(val, digits) | shft, x
  shft := (digits - 1) << 2
  repeat digits
    x := (val >> shft) & $F
    shft -= 4
    if (x => 10)
      x := (x - 10) + "A"
    else
      x := x + "0"
    tx(x)

The test program:
OBJ
  ser: "SmartSerial.spin2"

VAR
BYTE name[128]

PUB demo
  clkset(oscmode, freq)
  ser.start(63, 62, 0, baud)
  ser.str(string("Hello, there! What is your name? "))
  getname
  ser.str(string("Nice to meet you "))
  ser.str(@name[0])

PUB getname | c, i
  i := 0
  repeat
    c := ser.rx
    ser.tx(c)
    if (c == 8)
      if i > 0
        --i
    elseif c == 13 or c == 10
        quit
    else
        name[i++] := c
  name[i] := 0

Comments

  • evanhevanh Posts: 15,915
    Looks like a typo to me: "dirl rxpin" should be "dirh rxpin"
  • evanhevanh Posts: 15,915
    Very smooth integration of spin and assembly you've got there btw! I'm guessing variables default to cogRAM and code is hubexec. What happens if you want to have a 10kB array?

  • evanh wrote: »
    Looks like a typo to me: "dirl rxpin" should be "dirh rxpin"

    D'oh! I was thinking in terms of dumb pins, where the rxpin is set as an input by setting DIRA[pin] to 0. But you're right, for the smart pin I need dirh. Thanks!
  • evanh wrote: »
    Very smooth integration of spin and assembly you've got there btw! I'm guessing variables default to cogRAM and code is hubexec. What happens if you want to have a 10kB array?

    Only local variables (inside functions) are in COG memory. The VAR variables are in HUB.

    RIght now a 10kB local array probably won't work, but I plan on adding a check to force large arrays into HUB memory.

  • roglohrogloh Posts: 5,787
    edited 2019-01-02 23:17
    Yes such integration is very nice and having some similar inline pasm capability in the final spin2 language would be really cool too whenever it gets done. I do wonder if an "endasm" type of statement is really required, assuming indented code is also used. Seeing it in there just seems less "spin-ish" to me, but maybe it is needed for other reasons...? I could imagine it gets complex when you intermingle between the two languages in the parser.

    Also I guess if you ever copy/paste pasm code into this spin, you'd need to ensure the indenting is okay which could get tedious if you don't have the endasm.
  • jmgjmg Posts: 15,173
    rogloh wrote: »
    ... I do wonder if an "endasm" type of statement is really required, assuming indented code is also used. Seeing it in there just seems less "spin-ish" to me, but maybe it is needed for other reasons...? I could imagine it gets complex when you intermingle between the two languages in the parser.
    I think endasm is needed, precisely because asm is not spin, and uses different indent rules.
    eg Not shown in the example, are asm labels, but usually they are placed left of the code columns, so needs an explicit 'asm-zone' delimiting.

Sign In or Register to comment.