| |
sertcp.pwp
//
// PicoWeb Project File "sertcp"
//
// This project has no Web pages. It instead uses a special user-defined
// TCP/IP port to send data to the serial port and/or receive data from
// the serial port.
//
// Each time a packet is received for the special TCP port any data that it
// contains will be transmitted to the PicoWeb serial port. Then any data
// waiting in the serial port input queue will be sent back. The serial port
// queue will be read and any characters found there will be sent back in one
// or more outgoing TCP packets until either (1) the end-of-line character
// is detected (set by #define SER_PORT_EOL_CHAR), (2) an inter-character
// timeout is exceeded (set be #define SER_PORT_TIMEOUT_MSECS), or (3) the
// maximum number of character allowed in a response packet is exceeded (set
// by #define SER_MAX_CHARS 1024). The #define SER_CLEAR_QUEUE determines
// whether the serial port queue is cleared each time a new packet is
// received.
//
// Note that there is no "automatic" TCP/IP buffering/retry logic involved
// in these transactions. Therefore, if the remote host decides it needs to
// retransmit a packet, duplicate packets will be sent to the PicoWeb and
// they will be sent out the serial port. Likewise, serial data read from
// the serial port can be lost if the TCP/IP packets used to deliver this
// data back to the remote host are lost. Therefore, to insure "proper"
// adherence to the TCP/IP standard we need to assume that what is being sent
// to the serial port is something like a "command", with length less than
// one Ethernet packet (i.e., <1400 bytes), and that each unique command
// results in a fixed-length response from a device on the serial port.
// The length of this response should be less than the TCP/IP window
// size (typically <8 Kbytes). With these "rules", if the remote host's
// TCP/IP stack decides it needs retransmit an Ethernet packet, it will
// get more-or-less the same response back. Note that if the serial
// port "response packet" is kept under one packet in length, then a
// variable-length response can be returned.
//
// Testing:
//
// The following can be used to send/read data from a PicoWeb loaded with
// this project:
//
// httpget -r -S "Hello world!\r\n" 10.1.2.3:1000
//
// Note the PicoWeb is at IP address 10.1.2.3 in the above example.
// The ":1000" specified TCP port 1000 (defined in the project using
// define SEND_CMD_PORT). You need the "-r and -S" switches before the
// "command" string. Note the "\r" and "\n" in the command string which
// calls out a CR and LF.
//
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// NOTE!! Sending a zero-length packet to the PicoWeb causes the
// PicoWeb to very quietly ignore the packet!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
#define EEPROM_IP /* IP address stored in EEPROM */
#define NET_CONFIG_IP /* allow IP address reconfiguration via net */
#define ENABLE_WATCHDOG
#undef DEBUGGER /* no debugger...we're using serial port */
//#define CLOCK 8000000
#define CLOCK 7372000
#define BAUD_RATE 19200
#define BLINK_LED /* will blink PicoWeb LED on TCP serial I/O */
#define UNKNOWN_TCP_PORT_HANDLER our_tcp_handler
#define SEND_CMD_PORT 1000 /* port to send pure binary data */
#define SEND_TCMD_PORT 999 /* port to send URL-style %XX quoted data */
#define SER_PORT_TIMEOUT_MSECS 1000 /* serial port input timeout */
#define SER_PORT_EOL_CHAR 0x0d /* serial input end-of-line character */
/* don't define for no EOL processing */
#define SER_MAX_CHARS 1024 /* max. characters allowed in response packet */
#define SER_CLEAR_QUEUE /* define to clear input queue before each burst out */
// HTML and images
// public CGI routines
// linker directives (search or add)
//------------------ included AVR assembly language follows ---------------
#avr_reset
#define putchar_serial pmovbi putc_b,0
#define putchar_net pmovbi putc_b,1
#define serial_binary pser_mode 1
#define serial_normal pser_mode 0
#ifdef BLINK_LED
#define LED_ON cbi portd,LED_BIT /* turn LED on */
#define LED_OFF sbi portd,LED_BIT /* turn LED off */
#define PLED_ON pledon /* turn LED on with pcode */
#define PLED_OFF pledoff /* turn LED off with pcode */
sbi DDRD,LED_BIT ; make LED driver pin an output
LED_OFF ; turn LED off
#else /* !BLINK_LED */
#define LED_ON
#define LED_OFF
#define PLED_ON
#define PLED_OFF
#endif /* !BLINK_LED */
.cseg
serial_binary ; serial port to binary mode (clears queue)
.eseg
#avr_slow
.cseg
.eseg
#avr_fast
#avr_asm
#ifdef BLINK_LED
pledon: pcode_routine 0
LED_ON
ret
pledoff: pcode_routine 0
LED_OFF
ret
#endif /* BLINK_LED */
;
; serdev_copynet
;
; loop reading chars from the serial buffer and writing to ''net until
; CR encountered (or timeout)
;
.cseg
serdev_copynet:
pmovwi buf+2,SER_MAX_CHARS ; zero max. character counter
serdev_copynet_loop:
; get char from serial port with TO
psgetcto buf,PSGETCTO_MSECS(SER_PORT_TIMEOUT_MSECS)
pjumpeq serdev_copydone ; no more chars!
#ifdef SER_PORT_EOL_CHAR
pcmpbi buf,SER_PORT_EOL_CHAR ; check for EOL character (exit if found)
pjumpeq serdev_copydone
#endif
pputcb buf ; output character
pdecw buf+2 ; decrement character counter
pjumpeq serdev_copydone ; exit now if counter hit zero
pjump serdev_copynet_loop ; back for more
serdev_copydone:
pret
;
; Our handler for unknown TCP ports
;
#define MY_TCP_OFFSET buf
#define MY_TCP_LEN buf+2
#define MY_TCP_CHAR buf+4
.cseg
our_tcp_handler:
pcmpwi buf,BSWAP(SEND_CMD_PORT) ; check for our special TCP port
pjumpeq tcp_send_cmd ; process TCP packet if ours
#ifdef SEND_TCMD_PORT
pcmpwi buf,BSWAP(SEND_TCMD_PORT); check for our special TCP port
pjumpeq tcp_send_tcmd ; process TCP packet if ours
#endif
pret ; not for us...exit
#ifdef SEND_TCMD_PORT
tcp_send_tcmd:
pcall tcp_enable_serial ; enable serial port
pmovwi MY_TCP_OFFSET,[data_addr]; get start of TCP packet data
pprinturl MY_TCP_OFFSET,1 ; send URL-style "quoted" data
pjump tcp_send_response ; copy serial port input to net and exit
#endif
tcp_enable_serial:
PLED_ON
ppushn putcok,1 ; enable output after saving state
pmovbi putcok,1
putchar_serial ; switch putchar to serial port
#ifdef SER_CLEAR_QUEUE
serial_binary ; serial port to binary mode (clears queue)
#endif
pret
tcp_send_cmd:
pcall tcp_enable_serial ; enable serial port
pmovwi MY_TCP_OFFSET,[data_addr]; get start of TCP packet data
pmovwi MY_TCP_LEN,[data_len] ; get length of TCP packet data
pcmpwi MY_TCP_LEN,0 ; zero?
;;;pprintv "MY_TCP_LEN=",[MY_TCP_LEN]
;;;pcrlf
pjumpeq tcp_send_response ; yes...early exit
tcp_send_raw:
pr2s MY_TCP_CHAR,[MY_TCP_OFFSET],1; get next byte
pputcb MY_TCP_CHAR ; write character to serial port
pincw MY_TCP_OFFSET ; bump receive packet pointer
pdecw MY_TCP_LEN ; decrement count
pjumpne tcp_send_raw ; back for more if non-zero
tcp_send_response:
putchar_net ; switch putchar back to ''net
pcall serdev_copynet ; copy serial port input to net
ppopn putcok,1 ; restore state
PLED_OFF
pret
Back
|
|
|