Spinneret server html problem
Hello,
I have a project, my project is to control the lights, doors, temperature and other things .. from anywhere in the world.
You can see the website http://108.171.79.7:5555/index.htm
I have a Proppeler as a client and a Spinneret as a server that communicates via two wire serial RX and TX to the client how control all.
The site works fine but I'd like to see all the states in the same web page. I tried several things but I think my problem is in the html code ... Look at the code and tell me what you think. What can I do to show all the states "On" or "Off" on the same page?
On the Spinneret
The Client code
RX
TX
[code]{{
*****************************************************
* High Speed Prop to Prop Comm Transmitter v1.1 *
* *
* Author: Beau Schwabe *
* Copyright (c) 2011 Parallax *
* See end of file for terms of use. *
*****************************************************
Revision History:
Version 1.0 - original file created as a high speed Prop to Prop
Version 1.1 - (03-29-2011) added routines to aid in handshaking
as well as data packet re-direction.
≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
The Anatomy of the packet data:
When Sending (TX) You must indicate in the PacketHeader what address you want the
data to come from. Additionally the Dest Offset tells the receiver the amount of
offset in LONGs of where the data will be written on the receiver side. The Dest
Offset value overwrites the position of the Data Address prior to sending the first
Packet so that the Dest Offset value is sent rather than the Data Address.
The Data Command (Optional) is used to request a specific function from the receiver.
Note: The receiver must be programmed to know what to do with the command value.
Packet Size is also conveyed to the receiver, indicating how many packets the receiver
is to expect.
Note:
- Packet Size, counts as 1 packet itself, so if your packet data is 100 longs, then
the Packet Size should indicate 101.
- You must send at least 2 Packets for a valid transmission.
PacketHeader: 32-bit long
%ssssssssssssss_aaaaaaaaaaaaaa_cccc
└ Packet Size┘ └Data Address┘ │ │
14-Bits 14-Bits │ │
Data Command ; $0 - $E command to send to the receiver
4-Bits Note: $F is reserved to indicate Transmission is complete
- The data pin is only driven HIGH.
- A pull-down resistor of 330 Ohms on both the Server and the Client side of the data pin
keep the pin LOW.
Schematic:
22 22
Server ──┳────────────────────────┳── Client
330 330
GND GND
DataPacket dataline:
Packet Sync PacketHeader
│ │
│ │ Packet Data #1 Packet Data #N
3.3us 3.2us 3.2us 3.2us
TX ...ɧ
I have a project, my project is to control the lights, doors, temperature and other things .. from anywhere in the world.
You can see the website http://108.171.79.7:5555/index.htm
I have a Proppeler as a client and a Spinneret as a server that communicates via two wire serial RX and TX to the client how control all.
The site works fine but I'd like to see all the states in the same web page. I tried several things but I think my problem is in the html code ... Look at the code and tell me what you think. What can I do to show all the states "On" or "Off" on the same page?
On the Spinneret
{{
─────────────────────────────────────────────────
Copyright (c) 2011 AgaveRobotics LLC.
See end of file for terms of use.
File....... HTTPServer.spin
Author..... Mike Gebhard
Company.... Agave Robotics LLC
Email...... mailto:mike.gebhard@agaverobotics.com
Started.... 11/01/2010
Updated.... 07/16/2011
─────────────────────────────────────────────────
}}
{
About:
HTTPServer is the designed for use with the Spinneret Web server manufactured by Parallax Inc.
Usage:
HTTPServer is the top level object.
Required objects:
Parallax Serial Terminal.spin
W5100_Indirect_Driver.spin
S35390A_SD-MMC_FATEngineWrapper.spin
Request.spin
Response.spin
StringMethods.spin
S35390A_RTCEngine.spin
Change Log:
}
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
MAX_PACKET_SIZE = $5C0 '1472 '$800 = 2048
RxTx_BUFFER = $800 '$600 = 1536
TEMP_BUFFER = $600 '$5B4 = 1460
TCP_PROTOCOL = %0001 '$300 = 768
UDP_PROTOCOL = %0010 '$200 = 512
TCP_CONNECT = $04 '$100 = 256
DELAY = $10
MAX_TRIES = $25
#0, DONE, PUT, CD
RX_Pin = 27
TX_Pin = 26
Command = %0000 '' Feature not used in this demo
Offsett = 0 '' Feature not used in this demo
DAT
mac byte $00, $08, $DC, $16, $F2, $73
subnet byte 255, 255 ,255, 0
gateway byte 108,171,79,7 'WAN Default Gateway : 24.230.203.1
ip byte 192,168,0,105 'LAN
port word 5555
remoteIp byte 24,230,203,105 'http://www.whatismyip.com
remotePort word 80
uport word 5050
emailIp byte 0, 0, 0, 0
emailPort word 25
status byte $00, $00, $00, $00
rxdata byte $0[RxTx_BUFFER]
txdata byte $0[RxTx_BUFFER]
udpdata byte $0[TEMP_BUFFER]
fileErrorHandle long $0
debug byte $0
lastFile byte $0[12], 0
closedState byte %0000
openState byte %0000
listenState byte %0000
establishedState byte %0000
closingState byte %0000
closeWaitState byte %0000
lastEstblState byte %0000
lastEstblStateDebug byte %0000
udpListen byte %0000
tcpMask byte %1111
udpMask byte %1000
fifoSocketDepth byte $0
fifoSocket long $00_00_00_00
debugSemId byte $00
debugCounter long $00
stringMethods long $00
closingTimeout long $00, $00, $00, $00
udpLen long $00
time byte "00/00/0000 00:00:00", 0
httpDate byte "Wed, 01 Feb 2000 01:00:00 GMT", 0
globalCache byte $1
NB0 BYTE 999,0
NB1 BYTE 1,0
NB2 BYTE 2,0
NB3 BYTE 3,0
NB4 BYTE 4,0
NB5 BYTE 5,0
NB6 BYTE 6,0
NB7 BYTE 7,0
NB8 BYTE 8,0
NB9 BYTE 9,0
NB22 BYTE 22,0
VAR
long StackSpace[20]
BYTE Buffer[10],Buffer1[10],Pin[10]
OBJ
pst : "Parallax Serial Terminal"
Socket : "W5100_Indirect_Driver"
SDCard : "S35390A_SD-MMC_FATEngineWrapper"
Request : "Request"
Response : "Response"
str : "StringMethods"
rtc : "S35390A_RTCEngine"
hsRX : "HSp2pRX" 'High Speed Receive driver
hsTX : "HSp2pTX" 'High Speed Transmit driver
PUB Initialize | id, size, st
debug := 1
SDCard.Start
stringMethods := str.Start
Request.Constructor(stringMethods)
Response.Constructor(stringMethods, @txdata)
pst.Start(115_200)
pause(200)
'Mount the SD card
pst.str(string("Mount SD Card - "))
SDCard.mount(fileErrorHandle)
pst.str(string("OK",13))
pst.str(string("Start RTC: "))
rtc.RTCEngineStart(29, 28, -1)
pause(200)
pst.str(FillTime)
'Start the W5100 driver
if(Socket.Start)
pst.str(string(13, "W5100 Driver Started", 13))
pst.str(string(13, "Status Memory Lock ID : "))
pst.dec(Socket.GetLockId)
pst.char(13)
if(debugSemId := locknew) == -1
pst.str(string("Error, no HTTP server locks available", 13))
else
pst.str(string("HTTP Server Lock ID : "))
pst.dec(debugSemId)
pst.char(13)
'Set the Socket addresses
SetMac(@mac)
SetGateway(@gateway)
SetSubnet(@subnet)
SetIP(@ip)
' Initailize TCP sockets (defalut setting; TCP, Port, remote ip and remote port)
repeat id from 0 to 3
InitializeSocket(id)
Request.Release(id)
pause(50)
' Set all TCP sockets to listen
pst.char(13)
repeat id from 0 to 3
Socket.Listen(id)
pst.str(string("TCP Socket Listener ID : "))
pst.dec(id)
pst.char(13)
pause(50)
pst.Str(string(13,"Started Socket Monitoring Service", 13))
cognew(StatusMonitor, @StackSpace)
pause(250)
pst.Str(string(13, "Initial Socket States",13))
StackDump
pst.Str(string(13, "Initial Socket Queue",13))
QueueDump
pst.str(string(13,"//////////////////////////////////////////////////////////////",13))
Main
PUB Main | packetSize, id, i, reset, j, temp
''HTTP Service
repeat
repeat until fifoSocket == 0
bytefill(@rxdata, 0, RxTx_BUFFER)
if(debug)
pst.str(string(13, "----- Start of Request----------------------------",13))
pause(DELAY)
else
pause(DELAY)
' Pop the next socket handle
id := DequeueSocket
if(id < 0)
next
if(debug)
pst.str(string(13,"ID: "))
pst.dec(id)
pst.str(string(13, "Request Count : "))
pst.dec(debugCounter)
pst.char(13)
packetSize := Socket.rxTCP(id, @rxdata)
reset := false
if ((packetSize < 12) AND (strsize(@rxdata) < 12))
repeat i from 0 to MAX_TRIES
pst.str(string(13,"* Retry *"))
'Wait for a few moments and try again
waitcnt((clkfreq/300 ) + cnt)
packetSize := Socket.rxTCP(id, @rxdata)
if(packetSize > 12)
quit
if(i == MAX_TRIES)
'Clean up resource request
Request.Release(id)
Socket.Disconnect(id)
reset := true
if(debug)
StackDump
pst.char(13)
QueueDump
pst.str(string(13,"* Timeout *",13))
if(reset)
next
Request.InitializeRequest(id, @rxdata)
if(debug)
pst.char(13)
HeaderLine1(id)
else
pause(DELAY)
' Process router
Dispatcher(id)
'Clean up request resource
Request.Release(id)
' This starts the close process -> 0x00
' use close to force a close
Socket.Disconnect(id)
bytefill(@txdata, 0, RxTx_BUFFER)
debugCounter++
GotoMain
PUB comm
repeat 1
dira[23]~~
outa[23]~
hsTX.TX(TX_Pin,10,@Buffer,Command,Offsett) '<- Transmit Data to External Propeller
hsRX.RX(RX_Pin,@Buffer)
!outa[23] '<- Receive Data from External Propeller
hsRX.RX(RX_Pin,@Buffer1)
hsTX.TX(TX_Pin,10,@Buffer1,Command,Offsett) '<- Transmit Data to External Propeller
!outa[23]
return
PRI SendLedResposne(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus(1)
Buffer[0] := 1
if (strcomp(string("off"), qstr ))
LedStatus(0)
Buffer[0] := 0
if (strcomp(string("what"), qstr ))
if(pin[0]) == 1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneA(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus1(1)
Buffer[1] := 1
if (strcomp(string("off"), qstr ))
LedStatus1(0)
Buffer[1] := 0
if (strcomp(string("what"), qstr ))
if(pin[1])== 1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneB(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus2(1)
Buffer[2] := 1
if (strcomp(string("off"), qstr ))
LedStatus2(0)
Buffer[2] := 0
if (strcomp(string("what"), qstr ))
if(pin[2])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneC(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus3(1)
Buffer[3] := 1
if (strcomp(string("off"), qstr ))
LedStatus3(0)
Buffer[3] := 0
if (strcomp(string("what"), qstr ))
if(pin[3])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneD(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus4(1)
Buffer[4] := 1
if (strcomp(string("off"), qstr ))
LedStatus4(0)
Buffer[4] := 0
if (strcomp(string("what"), qstr ))
if(pin[4])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneE(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus5(1)
Buffer[5] := 1
if (strcomp(string("off"), qstr ))
LedStatus5(0)
Buffer[5] := 0
if (strcomp(string("what"), qstr ))
if(pin[5])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneF(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus6(1)
Buffer[6] := 1
if (strcomp(string("off"), qstr ))
LedStatus6(0)
Buffer[6] := 0
if (strcomp(string("what"), qstr ))
if(pin[6])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneG(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus7(1)
Buffer[7] := 1
if (strcomp(string("off"), qstr ))
LedStatus7(0)
Buffer[7] := 0
if (strcomp(string("what"), qstr ))
if(pin[7])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneH(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus8(1)
Buffer[8] := 1
if (strcomp(string("off"), qstr ))
LedStatus8(0)
Buffer[8] := 0
if (strcomp(string("what"), qstr ))
if(pin[8])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI SendLedResposneI(id) | headerLen, qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
'' Exit if there is no querystring
if(qstr == 0)
return false
'' Turn the LED on if the led= value is "on"
if (strcomp(string("on"), qstr ))
LedStatus9(1)
Buffer[9] := 1
if (strcomp(string("off"), qstr ))
LedStatus9(0)
Buffer[9] := 0
if (strcomp(string("what"), qstr ))
if(pin[9])==1
qstr := string("on")
else
qstr := string("off")
'' Build and send the header
'' Send the value of led= on or off
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
Socket.txTCP(id, qstr, strsize(qstr))
comm
return true
PRI Dispatcher(id)
''Do some processing before sending the response
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aled.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposne(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aleda.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneA(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledb.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneB(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledc.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneC(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledd.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneD(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("alede.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneE(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledf.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneF(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledg.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneG(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledh.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneH(id))
return
Request.Get(id, string("led"))
if(strcomp(Request.GetFileName(id), string("aledi.htm")) AND Request.GetDepth(id) == 1)
if(SendLedResposneI(id))
return
StaticFileHandler(id)
return
PRI LedStatus(state)
pin[0] := state
return
PRI LedStatus1(stateA)
pin[1] := stateA
return
PRI LedStatus2(stateB)
pin[2] := stateB
return
PRI LedStatus3(stateC)
pin[3] := stateC
return
PRI LedStatus4(stateD)
pin[4] := stateD
return
PRI LedStatus5(stateE)
pin[5] := stateE
return
PRI LedStatus6(stateF)
pin[6] := stateF
return
PRI LedStatus7(stateG)
pin[7] := stateG
return
PRI LedStatus8(stateH)
pin[8] := stateH
return
PRI LedStatus9(stateI)
pin[9] := stateI
return
PRI GotoMain
Main
PRI StaticFileHandler(id) | fileSize, i, headerLen, temp, j
''Serve up static files from the SDCard
'pst.str(string(13,"Static File Handler",13))
SDCard.changeDirectory(@approot)
pst.char(13)
'Make sure the directory exists
ifnot(ChangeDirectory(id))
'send 404 error
WriteError(id)
SDCard.changeDirectory(@approot)
return
' Make sure the file exists
ifnot(FileExists(Request.GetFileName(id)))
'send 404 error
WriteError(id)
SDCard.changeDirectory(@approot)
return
' Open the file for reading
SDCard.openFile(Request.GetFileName(id), "r")
fileSize := SDCard.getFileSize
'WriteResponseHeader(id)
'BuildHeader(extension, statusCode, expirer)
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
if fileSize < MAX_PACKET_SIZE
' send the file in one packet
SDCard.readFromFile(@txdata, fileSize)
Socket.txTCP(id, @txdata, fileSize)
else
' send the file in a bunch of packets
repeat
SDCard.readFromFile(@txdata, MAX_PACKET_SIZE)
Socket.txTCP(id, @txdata, MAX_PACKET_SIZE)
fileSize -= MAX_PACKET_SIZE
' once the remaining fileSize is less then the max packet size, just send that remaining bit and quit the loop
if fileSize < MAX_PACKET_SIZE and fileSize > 0
SDCard.readFromFile(@txdata, fileSize)
Socket.txTCP(id, @txdata, fileSize)
quit
' Bailout
if(i++ > 1_000_000)
WriteError(id)
quit
SDCard.closeFile
SDCard.changeDirectory(@approot)
return
PRI WriteError(id) | headerOffset
'' Simple 404 error
pst.str(string(13, "Write 404 Error",13 ))
headerOffset := Response.BuildHeader(Request.GetExtension(id), 404, false)
Socket.txTCP(id, @txdata, headerOffset)
return
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' directory and file handlers
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI ChangeDirectory(id) | i, found
'Handle directory structure for this Request
if(Request.GetDepth(id) > 1)
repeat i from 0 to Request.GetDepth(id)-2
'Return if the directory is not found
ifnot(FileExists(Request.GetPathNode(id, i)))
return false
found := SDCard.changeDirectory(Request.GetPathNode(id, i))
return true
PRI FileExists(fileToCompare) | filenamePtr
'Start file find at the top of the list
SDCard.startFindFile
'Verify that the file exists
repeat while filenamePtr <> 0
filenamePtr := SDCard.nextFile
if(str.MatchPattern(filenamePtr, fileToCompare, 0, false ) == 0 )
return true
return false
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' Time Methods and Formats
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI GetTime(id) | ptr, headerOffset
ptr := @udpdata
FillHttpDate
bytemove(ptr, string("<p>"),3)
ptr += 3
bytemove(ptr, @httpDate, strsize(@httpDate))
ptr += strsize(@httpDate)
bytemove(ptr, string("</p>"),4)
ptr += 3
headerOffset := Response.BuildHeader(Request.GetExtension(id), 200, false)
Socket.txTCP(id, @txdata, headerOffset)
StringSend(id, @udpdata)
bytefill(@udpdata, 0, TEMP_BUFFER)
return
PRI FillTime | ptr, num
'ToString(integerToConvert, destinationPointer)
'00/00/0000 00:00:00
ptr := @time
rtc.readTime
FillTimeHelper(rtc.clockMonth, ptr)
ptr += 3
FillTimeHelper(rtc.clockDate, ptr)
ptr += 3
FillTimeHelper(rtc.clockYear, ptr)
ptr += 5
FillTimeHelper(rtc.clockHour , ptr)
ptr += 3
FillTimeHelper(rtc.clockMinute , ptr)
ptr += 3
FillTimeHelper(rtc.clockSecond, ptr)
return @time
PRI FillHttpDate | ptr, num, temp
'ToString(integerToConvert, destinationPointer)
'Wed, 01 Feb 2000 01:00:00 GMT
ptr := @httpDate
rtc.readTime
temp := rtc.getDayString
bytemove(ptr, temp, strsize(temp))
ptr += strsize(temp) + 2
FillTimeHelper(rtc.clockDate, ptr)
ptr += 3
temp := rtc.getMonthString
bytemove(ptr, temp, strsize(temp))
ptr += strsize(temp) + 1
FillTimeHelper(rtc.clockYear, ptr)
ptr += 5
FillTimeHelper(rtc.clockHour , ptr)
ptr += 3
FillTimeHelper(rtc.clockMinute , ptr)
ptr += 3
FillTimeHelper(rtc.clockSecond, ptr)
return @httpDate
PRI FillTimeHelper(number, ptr) | offset
offset := 0
if(number < 10)
offset := 1
str.ToString(@number, @tempNum)
bytemove(ptr+offset, @tempNum, strsize(@tempNum))
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' SDCard Logger
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI AppendLog(logToAppend)
'' logToAppend: Pointer to a string of test we'd like to log
SDCard.changeDirectory(@approot)
if(FileExists(@logfile))
SDCard.openFile(@logfile, "A")
else
SDCard.newFile(@logfile)
SDCard.writeData(string(13,10,"----- Start "),14)
SDCard.writeData(FillTime, 19)
SDCard.writeData(string(" -----"),6)
SDCard.writeData(@crlf_crlf, 2)
SDCard.writeData(logToAppend, strsize(logToAppend))
SDCard.writeData(@crlf_crlf, 2)
SDCard.writeData(string("----- End "),10)
SDCard.writeData(FillTime, 19)
SDCard.writeData(string(" -----"),6)
SDCard.writeData(@crlf_crlf, 2)
SDCard.closeFile
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' Memory Management
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI Set(DestAddress, SrcAddress, Count)
bytemove(DestAddress, SrcAddress, Count)
bytefill(DestAddress+Count, $0, 1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' Socekt helpers
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI GetTcpSocketMask(id)
return id & tcpMask
PRI DecodeId(value) | tmp
if(%0001 & value)
return 0
if(%0010 & value)
return 1
if(%0100 & value)
return 2
if(%1000 & value)
return 3
return -1
PRI QueueSocket(id) | tmp
if(fifoSocketDepth > 4)
return false
tmp := |< id
'Unique check
ifnot(IsUnique(tmp))
return false
tmp <<= (fifoSocketDepth++) * 8
fifoSocket |= tmp
return true
PRI IsUnique(encodedId) | tmp
tmp := encodedId & $0F
repeat 4
if(encodedId & fifoSocket)
return false
encodedId <<= 8
return true
PRI DequeueSocket | tmp
if(fifoSocketDepth == 0)
return -2
repeat until not lockset(debugSemId)
tmp := fifoSocket & $0F
fifoSocket >>= 8
fifoSocketDepth--
lockclr(debugSemId)
return DecodeId(tmp)
PRI ResetSocket(id)
Socket.Disconnect(id)
Socket.Close(id)
PRI IsolateTcpSocketById(id) | tmp
tmp := |< id
tcpMask &= tmp
PRI SetTcpSocketMaskById(id, state) | tmp
'' The tcpMask contains the socket the the StatusMonitor monitors
tmp := |< id
if(state == 1)
tcpMask |= tmp
else
tmp := !tmp
tcpMask &= tmp
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' W5100 Helper methods
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI GetCommandRegisterAddress(id)
return Socket#_S0_CR + (id * $0100)
PRI GetStatusRegisterAddress(id)
return Socket#_S0_SR + (id * $0100)
PRI SetMac(_firstOctet)
Socket.WriteMACaddress(true, _firstOctet)
return
PRI SetGateway(_firstOctet)
Socket.WriteGatewayAddress(true, _firstOctet)
return
PRI SetSubnet(_firstOctet)
Socket.WriteSubnetMask(true, _firstOctet)
return
PRI SetIP(_firstOctet)
Socket.WriteIPAddress(true, _firstOctet)
return
PRI StringSend(id, _dataPtr)
Socket.txTCP(id, _dataPtr, strsize(_dataPtr))
return
PRI SendChar(id, _dataPtr)
Socket.txTCP(id, _dataPtr, 1)
return
PRI SendChars(id, _dataPtr, _length)
Socket.txTCP(id, _dataPtr, _length)
return
PRI InitializeSocket(id)
Socket.Initialize(id, TCP_PROTOCOL, port, remotePort, @remoteIp)
return
PRI InitializeSocketForEmail(id)
Socket.Initialize(id, TCP_PROTOCOL, port, emailPort, @emailIp)
return
PRI InitializeUPDSocket(id)
Socket.Initialize(id, UDP_PROTOCOL, uport, remotePort, @remoteIp)
return
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' Debug/Display Methods
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI QueueDump
'' Display socket IDs in the queue
'' ie 00000401 -> socket Zero is next to pop off
pst.str(string("FIFO["))
pst.dec(fifoSocketDepth)
pst.str(string("] "))
pst.hex(fifoSocket, 8)
PRI StackDump | clsd, open, lstn, estb, clwt, clng, id, ulst
'' This method is purely for debugging
'' It displays the status of all socket registers
repeat until not lockset(debugSemId)
clsd := closedState
open := openState
lstn := listenState
estb := establishedState
clwt := closeWaitState
clng := closingState
ulst := udpListen
lockclr(debugSemId)
pst.char(13)
repeat id from 3 to 0
pst.dec(id)
pst.str(string("-"))
pst.hex(status[id], 2)
pst.str(string(" "))
pause(1)
pst.str(string(13,"clsd open lstn estb clwt clng udps", 13))
pst.bin(clsd, 4)
pst.str(string("-"))
pst.bin(open, 4)
pst.str(string("-"))
pst.bin(lstn, 4)
pst.str(string("-"))
pst.bin(estb, 4)
pst.str(string("-"))
pst.bin(clwt, 4)
pst.str(string("-"))
pst.bin(clng, 4)
pst.str(string("-"))
pst.bin(ulst, 4)
pst.char(13)
PRI HeaderLine1(id) | i
pst.str(Request.GetMethod(id))
pst.char($20)
i := 0
repeat Request.GetDepth(id)
pst.char($2F)
pst.str(Request.GetPathNode(id, i++))
PRI Pause(Duration)
waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt)
return
PRI StatusMonitor | id, tmp, value
'' StatusMonitor is the heartbeat of the project
'' Here we monitor the state of the Wiznet 5100's 4 sockets
repeat
Socket.GetStatus32(@status[0])
' Encode status register states
repeat until not lockset(debugSemId)
closedState := openState := listenState := establishedState := {
} closeWaitState := closingState := 0
repeat id from 0 to 3
case(status[id])
$00: closedState |= |< id
closedState &= tcpMask
$13: openState |= |< id
openState &= tcpMask
$14: listenState |= |< id
listenState &= tcpMask
$17: establishedState |= |< id
establishedState &= tcpMask
$18,$1A,$1B: closingState |= |< id
closingState &= tcpMask
$1C: closeWaitState |= |< id
closeWaitState &= tcpMask
$1D: closingState |= |< id
closingState &= tcpMask
$22: udpListen |= |< id
udpListen &= udpMask
if(lastEstblState <> establishedState)
value := establishedState
repeat while value > 0
tmp := DecodeId(value)
if(tmp > -1)
QueueSocket(tmp)
tmp := |< tmp
tmp := !tmp
value &= tmp
lastEstblState := establishedState
lockclr(debugSemId)
' Initialize a closed socket
if(closedState > 0)
id := DecodeId(closedState)
if(id > -1)
InitializeSocket(id & tcpMask)
'Start a listener on an initialized/open socket
if(openState > 0)
id := DecodeId(openState)
if(id > -1)
Socket.Listen(id & tcpMask)
' Close the socket if the status is close/wait
' response processor should close the socket with disconnect
' there could be a timeout so we have a forced close.
' TODO: CCheck for a port that gets stuck in a closing state
'if(closeWaitState > 0)
'id := DecodeId(closeWaitState)
'if(id > -1)
'Socket.Close(id & tcpMask)
'pause(100)
return
DAT
approot byte "\", 0
defaultpage byte "index.htm", 0
logfile byte "log.txt", 0
'binFile byte "filename.bin", 0
FS byte "/", 0
fn byte "filename=", 0
doublequote byte $22, 0
crlf byte 13, 10, 0
crlf_crlf byte 13, 10, 13, 10, 0
uploadfile byte $0[12], 0
uploadfolder byte "uploads", 0
tempNum byte "0000",0
multipart byte "Content-Type: multipart/form-data; boundary=",0
boundary byte $2D, $2D
boundary1 byte $0[64]
'loadme file "TogglePin0.binary"
The Client code
{{
***************************************
* HighSpeed Client DEMO v1.0a *
* Author: Beau Schwabe *
* Copyright (c) 2011 Parallax, Inc. *
* See end of file for terms of use. *
***************************************
Revision History:
Version 1.0 - (09/20/2011) initial release
Version 1.0a - (09/26/2011) minor change to detect When the USB plug is connected
to the PC. This prevents unwanted resets.
}}
CON
' Set up the processor clock in the standard way for 80MHz on DemoBoard
_CLKMODE = xtal1 + pll16x
_XINFREQ = 5_000_000 + 0000
RX_Pin = 26
TX_Pin = 27
Command = %0000 '' Feature not used in this demo
Offset = 0 '' Feature not used in this demo
USB_Rx = 31
USB_Tx = 30
RANGE = 23 'Range is 0 to RANGE.
SAMPLES = 2 'Number of samples to pick: 1 to RANGE + 1
temps = 1
{{
Round Robin configuration using 2 Propellers:
┌────────────────────────────//────────────────────────────┐
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Propeller 1 │ │ Propeller 2 │ │
┣─┤RX TX├──┳───//───┳─┤RX TX├──┫
 │ Client │   │ Server │ 
 └─────────────────┘   └─────────────────┘ 
Vss Vss Vss Vss
Round Robin configuration using 3 or more Propellers:
┌────────────────────────────/.../────────────────────────────────/.../────────────────────────────┐
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Propeller 2 │ │ Propeller N │ │ Propeller 1 │ │
┣─┤RX TX├──┳───/.../───┳─┤RX TX├──┳───/.../───┳─┤RX TX├──┫
 │ Client │   │ Client │   │ Server │ 
 └─────────────────┘   └─────────────────┘   └─────────────────┘ 
Vss Vss Vss Vss Vss Vss
Note: All resistors tied to Vss are 330 Ohm and are there to establish a transmission line
Note: All resistors between TX and RX are 100 Ohm and are there to current limit the I/O's in the chance
of a collision.
With round robin, the idea is that you have one buffer that propagated around and around inside the
round robin loop. To avoid any data collisions, all Propellers are capable of reading any location
within the buffer, however each Propeller has a specific (assigned by the programmer) location that
it can write to.
So in the Demo, there is a 1K long buffer (4K bytes). As an example Propeller 1 may only write to
locations 0 to 255. While Propeller 2 can write to locations 256 to 511. Propellers 3 & 4 depicted
as N because of the expandable nature of round robin would write to the remaining 512 to 1023 locations.
}}
VAR
BYTE Buffer[10],Buffer1[10]
long Stack[400],Stack1[400]
byte numbers[RANGE + 1]
long seed
long keycode
OBJ
hsRX : "HSp2pRX" 'High Speed Receive driver
hsTX : "HSp2pTX" 'High Speed Transmit driver
PST : "Parallax Serial Terminal" 'RS232 Serial Driver
PUB Main
cognew(start,@Stack1)
PUB start|debugLED
'-------------------------------------------------------------------------------------------
if ina[USB_Rx] == 0 '' Check to see if USB port is powered
outa[USB_Tx] := 0 '' Force Propeller Tx line LOW if USB not connected
else
cognew(SerialDisplay,@Stack) '' Initialize serial communication to the PC
'-------------------------------------------------------------------------------------------
dira[16..23]~~ '<- I/O direction for debug LEDs
'-------------------------------------------------------------------------------------------
repeat
hsRX.RX(RX_Pin,@Buffer) '<- Receive Data from External Propeller
hsTX.TX(TX_Pin,10,@Buffer,Command,Offset) '<- Transmit Data to External Propeller
hsTX.TX(TX_Pin,10,@Buffer1,Command,Offset) '<- Transmit Data to External Propeller
hsRX.RX(RX_Pin,@Buffer1)
Menu_Principal
'-------------------------------------------------------------------------------------------
'-------------------------------------------------------------------------------------------
PUB SerialDisplay 'DEBUG ONLY
PST.Start(19200)
repeat
PST.HOME
PST.dec(Buffer) '<- Display Data
PUB Menu_Principal
outa[16] := Buffer[0]
outa[17] := Buffer[1]
outa[18] := Buffer[2]
outa[19] := Buffer[3]
outa[20] := Buffer[4]
outa[21] := Buffer[5]
PUB RANDOM | i, j, sample1, sample2
repeat 10
repeat i from 10 to RANGE 'Fill numbers array in order.
numbers[i] := i
repeat i from 10 to (SAMPLES - 1)
j := ||?seed // (RANGE - i + 1) + i 'Pick a number at random from the remaining choices.
sample1 := numbers[j]
bytemove(@numbers[i + 1], @numbers[i], j - i) 'Shift the values to make room.
numbers[i] := sample1
if sample1 < sample2
sample2 := sample1
waitcnt( _xinfreq / temps +cnt)
outa[16..23]~
waitcnt( _xinfreq / temps +cnt)
!outa[sample2]
next
if sample1 > sample2
sample2 := sample1
waitcnt( _xinfreq / temps +cnt)
outa[16..23]~
waitcnt( _xinfreq / temps +cnt)
!outa[sample2]
next
if sample1 == sample2
j := ||?seed // (RANGE - i + 1) + i 'Pick a number at random from the remaining choices.
sample1 := numbers[j]
bytemove(@numbers[i + 1], @numbers[i], j - i) 'Shift the values to make room.
numbers[i] := sample1
next
'Put the selected number in the newly vacated spot.
bytemove(@Buffer1,@NB1,strsize(@NB1))
PUB LED
dira[16..23]~~
outa[16..23]~
repeat 10
outa[16]~
!outa[23]
waitcnt ( _xinfreq + cnt)
!outa[23]
!outa[22]
waitcnt ( _xinfreq + cnt)
!outa[22]
!outa[21]
waitcnt ( _xinfreq + cnt)
!outa[21]
!outa[20]
waitcnt ( _xinfreq + cnt)
!outa[20]
!outa[19]
waitcnt ( _xinfreq + cnt)
!outa[19]
!outa[18]
waitcnt ( _xinfreq + cnt)
!outa[18]
!outa[17]
waitcnt ( _xinfreq + cnt)
!outa[17]
!outa[16]
waitcnt ( _xinfreq + cnt)
outa[16]~
bytemove(@Buffer1,@NB2,strsize(@NB2))
DAT
NB1 BYTE 1,0
NB2 BYTE 2,0
CON
RX
{{
**************************************************
* High Speed Prop to Prop Comm Receiver v1.1 *
* *
* Author: Beau Schwabe *
* Copyright (c) 2011 Parallax *
* See end of file for terms of use. *
**************************************************
Revision History:
Version 1.0 - original file created as a high speed Prop to Prop
Version 1.1 - (03-29-2011) added routines to aid in handshaking
as well as data packet re-direction.
≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
The Anatomy of the packet data:
When Receiving (RX) You must indicate in the PacketHeaderOut where you
want the received data to be stored.
Note: If TX sends a Destination offset value it will be added to the Data Address value
and the incomming data will be written starting at the new offset location.
The Data Ready Flag is automatically set in the RX function.
PacketHeaderOut: 32-bit long
%00000000000000_aaaaaaaaaaaaaa_cccc
     
└──Reserved──┘ └Data Address┘ │ │
14-Bits 14-Bits │ │
Data Ready Flag ; $0-busy $F-ready ... controlled by RX
4-Bits
After data has been received then PacketHeaderIn contains information from the
transmitter such as Packet Size, Dest Offset (This is the offset value applied to the local
data address), and a Command Packet that provides a way for the transmitter side to send
specific instructions to the receiver side.
PacketHeaderIn: 32-bit long
%ssssssssssssss_aaaaaaaaaaaaaa_cccc
     
└ Packet Size┘ └ Dest Offset┘ │ │
14-Bits 14-Bits │ │
Packet Command
4-Bits
- The data pin is only driven HIGH. This is similar to an open collector mode with a PNP drive transistor.
- A pull-down resistor of 330 Ohms on both the Server and the Client side of the data pin
keep the pin LOW.
Schematic:
22 22
Server ──┳────────────────────────┳── Client
 330 330 
 
GND GND
DataPacket dataline:
Packet Sync PacketHeader
│ │
│ │ Packet Data #1 Packet Data #N
   
3.3us 3.2us 3.2us 3.2us
TX ...
RX ...
 Packet #1 Packet #2 Packet #N
│
'Packet Sync' detected by RX, RX is ready to receive data
Note: TX monitors the Sync detection from RX and if TX doesn't see the response
from RX, then the 'Packet Sync' is sent again until it does.
TX must send at least 2 packets in order to be a valid transmission.
}}
PUB Stop 'Dumb code to prevent accidental running from this file
PUB RX(_Pin,_DataAddress)|PacketHeaderOut,PacketHeaderIn
PacketHeaderOut := _DataAddress<<4 'Tell PacketHeader where to put the Data it receives
Pin := _Pin 'Set receive pin to listen on
cognew(@RX_Propeller,@PacketHeaderOut) 'request data
repeat until (PacketHeaderOut& $F)==$F '<-- Trap here until RX is done
result := PacketHeaderIn 'return feedback data from transmitter
DAT
' Start RX proceedure ≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
RX_Propeller org
' Clear Status Flag ≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
rdlong DataSamples, par 'read data samples
andn DataSamples, #$F 'clear flag; data packet busy
wrlong DataSamples, par 'update flag status
' Get Address for Input Packet Header (Contents written here are from TX)
mov _PacketHeaderIn, par 'Read Data Address Location
add _PacketHeaderIn, #4
' Parse Output Packet Header so we know where to write the incomming data
rdlong Buff, par 'Read PacketHeader contents
mov DataIndex, Buff
and DataIndex, AddressMask 'DataIndex points to data buffer
shr DataIndex, #4
' Create Pin Mask for data transmission line
mov PinMask, #1 'Create Pin Mask for Input/Output pin
shl PinMask, Pin
or outa, PinMask 'Preset Pin HIGH
andn dira, PinMask 'Make Pin an INPUT Hi-Z LOW
' Setup Counter to count during data-pin HIGH times
movi ctra, #%0_11010_000 'LOGIC A
movs ctra, Pin
mov frqa, #1
' Detect 3.3us Packet SYNC
'' ... Detects a LOW-HIGH-LOW transition ; HIGH time must be at least 3.3us
Packet_SYNC
waitpne PinMask, PinMask 'Wait for LOW
mov phsa, #0 wz 'clear phsa and set Z flag
'Note: Z flag is used to
' Determine DataSamples
' further down in code
waitpeq PinMask, PinMask 'Wait for HIGH
waitpne PinMask, PinMask 'Wait for LOW
mov temp, phsa 'read phsa
cmp temp, #262 wc '<- 264 clocks at 80MHz equals 3.3us
if_c jmp #Packet_SYNC 'Jump if pulse is less than 3.3us
'' 3.3us pulse detected...
'' ... Respond by making dataline HIGH (Tell TX we're almost ready to receive)
or dira, PinMask 'Make pin HIGH
'' ... Respond by making dataline LOW (Tell TX to start sending data)
andn dira, PinMask 'Make Pin an INPUT Hi-Z LOW
'' Detect data long sync
'' ... wait for a HIGH of 100ns followed by a LOW of 50ns
_RX
waitpeq PinMask, PinMask 'Wait for HIGH
waitpne PinMask, PinMask 'Wait for LOW
' Read 1 LONG after sync ≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
test PinMask, ina wc 'Read RX pin into "C"
rcl Buff,#1 'Rotate Buff left and place "C" in Bit0
' Detect Packet Size with first received long ≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
if_z mov DataSamples, Buff 'Set first reading to number of DataSamples
if_z shr DataSamples, #18 'Clear "Z" flag in the dnjz below, so this
'only gets executed once.
' Write Data and get next long ≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
if_z wrlong Buff, _PacketHeaderIn 'Write received value to Start Address +4
if_z and Buff, AddressMask 'Parse data and add Dest Offset to Index
if_z shr Buff, #2
if_z add DataIndex, Buff
if_nz wrlong Buff, DataIndex 'Write received value to Indexed Address
if_nz add DataIndex, #4 'Increment Index value
djnz DataSamples, #_RX wz 'Check to see if there are more data samples
' Set Status Flag ≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
rdlong DataSamples, par 'read data samples
or DataSamples, #$F 'set flag; data packet done
wrlong DataSamples, par 'update flag status
' Terminate RX proceedure ≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
cogid temp 'Get this COG ID
cogstop temp 'STOP this COG
Pin long 0
PinMask long 0
Buff long 0
DataSamples long 0
DataIndex long 0
temp long 0
AddressMask long $7FFF0
_PacketHeaderIn long 0
delay long 0
DestOffset long 0
CON
TX
[code]{{
*****************************************************
* High Speed Prop to Prop Comm Transmitter v1.1 *
* *
* Author: Beau Schwabe *
* Copyright (c) 2011 Parallax *
* See end of file for terms of use. *
*****************************************************
Revision History:
Version 1.0 - original file created as a high speed Prop to Prop
Version 1.1 - (03-29-2011) added routines to aid in handshaking
as well as data packet re-direction.
≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
The Anatomy of the packet data:
When Sending (TX) You must indicate in the PacketHeader what address you want the
data to come from. Additionally the Dest Offset tells the receiver the amount of
offset in LONGs of where the data will be written on the receiver side. The Dest
Offset value overwrites the position of the Data Address prior to sending the first
Packet so that the Dest Offset value is sent rather than the Data Address.
The Data Command (Optional) is used to request a specific function from the receiver.
Note: The receiver must be programmed to know what to do with the command value.
Packet Size is also conveyed to the receiver, indicating how many packets the receiver
is to expect.
Note:
- Packet Size, counts as 1 packet itself, so if your packet data is 100 longs, then
the Packet Size should indicate 101.
- You must send at least 2 Packets for a valid transmission.
PacketHeader: 32-bit long
%ssssssssssssss_aaaaaaaaaaaaaa_cccc
└ Packet Size┘ └Data Address┘ │ │
14-Bits 14-Bits │ │
Data Command ; $0 - $E command to send to the receiver
4-Bits Note: $F is reserved to indicate Transmission is complete
- The data pin is only driven HIGH.
- A pull-down resistor of 330 Ohms on both the Server and the Client side of the data pin
keep the pin LOW.
Schematic:
22 22
Server ──┳────────────────────────┳── Client
330 330
GND GND
DataPacket dataline:
Packet Sync PacketHeader
│ │
│ │ Packet Data #1 Packet Data #N
3.3us 3.2us 3.2us 3.2us
TX ...ɧ

Comments
http://forums.parallax.com/showthread.php?142542-Using-AJAX-to-Update-a-Web-Page-in-Real-Time
As stated in the Propeller forum... use AJAX and XML to display multiple values on a single HTML page.