Spinneret server html problem
Podion
Posts: 90
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
Instead of send an XML document that contains a single element and value, send the XML document with all the data required to complete a single page. You'll have to update the JavaScript to parse the new XML node and place the values in the appropriate HTML tags.
See post 28 in the Spinneret forum for a similar question/answer. BTW, the Spinneret forum is a more appropriate location for this question.
Thank you.