receiving serial data with smartpins
ersmith
Posts: 6,224
in Propeller 2
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:
The test program:
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
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!
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.
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.
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.