📄 s7600.h
字号:
/////////////////////////////////////////////////////////////////////////
//// ////
//// s7600.h - Driver for the Seiko iReady s7600-A TCP/IP Stack ////
//// ////
//// This driver gives you all the necessary building blocks for ////
//// developing TCP/IP clients or servers. See the headers before ////
//// each function to see how they work. Also, CCS has provided two ////
//// example programs that use this driver: ////
//// ////
//// ex_email.c - A simple SMTP email client ////
//// ex_websv.c - A simple HTTP web server ////
//// ex_dnslookup.c - A simple DNS resolver client ////
//// ////
//// Many of the user configurable values, such as port locations ////
//// and timeout values, are located at the beginning of this file. ////
//// If you are using CCS's PICnet development board you do not need ////
//// to edit any of these values. ////
//// ////
//// If your ISP does not use PAP than you may have to edit the ////
//// login script in ppp_connect so it logs in properly. ////
//// ////
//// There are some bugs with the s7600 that you should be aware of. ////
//// First, the s7600 cannot handle padded PPP packets. Recently ////
//// some ISPs have started using equipment that pad PPP packets ////
//// until each packet hits a certain size of bytes. This breaks ////
//// the internal checksum mechanism of the s7600 and cannot be fixed////
//// in firmware. Another bug is that the s7600 cannot handle URG ////
//// packets. URG packets are most commonly used in the Telnet ////
//// protocol. You can design a pseudo telnet client/server if you ////
//// use RAW protocol (some Telnet clients will let you specify RAW ////
//// protocol instead of Telnet). Both of these bugs are fixed in ////
//// the rarer and more expensive s7601. This driver should work ////
//// in the s7601 if used in s7600 emulation mode, but has not been ////
//// tested. ////
//// ////
//// Something else to be aware of, which is not a bug, is that many ////
//// ISPs these days do not allow low speed modem connections, ////
//// rendering all those inexpesive and enticing 2400bps modem ////
//// modules obsolete. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// UPDATES: ////
//// ////
//// August 19th, 2003: Some PAP Fixes ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
/////////////////////////////////////////////////////////////////////////
//change the following lines to specify which port is connect to the s7600 address data/port
//this is set to correspond with CCS's picnet board (port D)
#ifndef s7600_busout
#define s7600_busout(x) output_d(x)
#define s7600_busin(x) input_d(x)
#define s7600_busfloat() set_tris_d(0xFF)
#define s7600_buscontrol() set_tris_d(0)
#endif
//change these defines to specify which pins are connected to your parts
//these are set to correspond with CCS's picnet board
#ifndef s7600_cs
#define s7600_cs PIN_B1
#define s7600_rs PIN_B2
#define s7600_readx PIN_B3
#define s7600_writex PIN_B4
#define s7600_busyx PIN_C4
#define s7600_resetx PIN_C5
#define modem_reset PIN_B5
#define modem_dcd PIN_C3
#endif
//do not change these values, you must design your board this way if you want to have the s7600 interrupt the PIC,
// and you must leave it this way if you want the PWM to generate a clock for the s7600.
//CCS code doesn't enable s7600 interrupts, it uses a polling method on the s7600. Therefore B0 is free, but still defined
#ifndef s7600_int1
#define s7600_int1 PIN_B0 //set to b0 to use int_ext to get interrupts from s7600
#endif
#ifndef s7600_clk
#define s7600_clk PIN_C2 //set to c2 to use pwm to generate clock source for s7600
#endif
//set this to true if you want to send debug information out the rs232 port
#define DO_DEBUG TRUE
#ifndef debug
#if DO_DEBUG
#define debug printf
#else
#define debug
#endif
#endif
//set true if your ISP uses PAP authentication to authenticate logins.
#ifndef USE_PAP
#define USE_PAP FALSE
#endif
//set to true if your modem is connected to the s7600 with rts/cts hardware flow control
//this is set to correspond with CCS's picnet board. (no hwfc)
#define USE_HWFC FALSE
//this is your modem init string, sent before a dial
#if USE_HWFC
#define MODEM_INIT "ATM1L3" //speaker on, volume high
#else
#define MODEM_INIT "ATM1L3&K0" //speaker on, volume high, no hw flow control
#endif
//if you are running a board different than CCS's PICnet then you need to either recalculate
// the timing done in s7600_init_clock() or define these values correctly and let the mcu calculate
// timing in real time.
//if you decide to calculate in real time (which will eat up ROM in floating point math) then
// CLOCK_FREQ is the speed of the mcu, and s7600_CLOCK_FREQ is the clock speed of the s7600
#define CLOCK_FREQ 19660000
#define s7600_CLOCK_FREQ 702143
//just in case future s76xx have more than 2 sockets, if so specify how many here
#define MAX_SOCKET 2
//these define a few timeout and timing values, in ms
#define REDIAL_DELAY 1000
#define MODEM_CONNECT_RETRY 5
#define MODEM_RESPONSE_TIMEOUT 2000
#define MODEM_CONNECT_TIMEOUT 60000 //time for two modems to connect and handshake
#define PPP_DISCONNECT_TIMEOUT 500
#define PPP_RESET_TIMEOUT 5000 //time to wait for PPP peripheral to reset
#define PPP_CONNECT_TIMEOUT 30000 //time to wait for PPP authentication
#define TCP_TIMEOUT 20
#define TCP_CONNECT_TIME 5000
/*!*!*!*! END USER CONFIGURATION !*!*!*!*/
typedef int32 IPAddr;
IPAddr MyIPAddr; //global variable that contains your IP address
enum s7600_ec {
BAD, OK, TIMEOUT, PPP_FROZEN, //0-3
NO_MODEM_RESPONSE, NO_CARRIER, NO_FREE_SOCKET, INVALID_SOCKET, //4-7
SOCKET_SND_BUSY, SOCKET_NOT_CONNECTED, SOCKET_NOT_ACTIVATED, NO_BUFFER_SPACE, //8-11
SOCKET_CLOSE_TIMEOUT, PPP_NOT_CONNECTED, NO_PPP_DISCONNECT, MODEM_CONNECTED, //12-15
MODEM_BUSY_SIGNAL, MODEM_NO_DIALTONE, ID_FAIL, INVALID_CS, //16-19
SERVER_ERROR, DNS_FAIL //20
};
//high level function prototypes. functions for use in developing embedded internet applications
void tcpip_init();
int8 tcp_connect(IPAddr ip, int16 portnum, int8 socket);
int8 tcp_find_free_socket(void);
void tcp_listen(int8 socket, int16 port);
int8 tcp_getc(int8 socket);
int1 tcp_kbhit(int8 socket);
void tcp_flush_socket(int8 socket);
int1 tcp_connected(int8 socket);
s7600_ec tcp_putc(int8 socket, int8 c);
s7600_ec tcp_putd(int8 socket, int8 * c, int16 len);
void tcp_close(int8 socket);
int1 ppp_check(void);
s7600_ec ppp_connect(int8 * phone_number, int8 * username, int8 * password);
void ppp_disconnect(void);
void ppp_keepalive(void);
//mid level function prototypes; general purpose functions used by above high level functions
//void modem_reset(void);
s7600_ec modem_connect(int8 * phone_number);
s7600_ec modem_disconnect(void);
s7600_ec modem_response(int16 to);
void s7600_init(void);
void s7600_free_sockets(void);
void s7600_init_clock(void);
void s7600_Serial_Write(int8 data);
int1 s7600_Serial_kbhit(void);
int8 s7600_Serial_Read(void);
void s7600_Serial_Flush(void);
void s7600_Socket_Write(int8 data);
int8 s7600_Socket_Read(void);
//low level function prototypes; lowest level functions used by above functions
void s7600_DMA_Write(int8 address, int8 data);
int8 s7600_DMA_Read(int8 address);
//These are register addresses on the s7600 chip
#define IR_VERSION 0x00
#define IR_GENERAL 0x01
#define SOCKET_LOCATION_REG 0x02
#define IR_PORT_STAT_REG 0x08
#define IR_PORT_DATA_REG 0x0B
#define IR_BAUD_DIVIDER 0x0C
#define IR_OUR_IP 0x10
#define IR_CLOCK_DIV 0x1C
#define SOCKET_SELECT_REG 0x20
#define SOCKET_TOS_REG 0x21
#define SOCKET_STATUS_REG 0x22
#define SOCKET_ACTIVATE_REG 0x24
#define SOCKET_DATA_AVAILABLE 0x28
#define SOCKET_DATA_REG 0x2E
#define SOCKET_SEND_DATA 0x2E
#define SOCKET_BUFFER_OUT_SIZE 0x30
#define SOCKET_BUFFER_IN_SIZE 0x32
#define SOCKET_URGENT_DATA_ADDR 0x34
#define SOCKET_PEER_PORT 0x36
#define SOCKET_OUR_PORT 0x38
#define SOCKET_STATUS_HIGH 0x3A
#define SOCKET_PEER_IP_ADDR 0x3C
#define IR_PPP_STATUS_REG 0x60
#define IR_PPP_MAX_RETRY 0x62
#define IR_PPP_DATA 0x63
#define IR_PAP_STRING 0x64
#define IR_PPP_STATE 0x6E
#separate
void display_error(char * string, s7600_ec error) {
debug("\r\n%s: ",string);
switch(error) {
case BAD:
debug("GENERAL ERROR"); break;
case OK:
debug("OK"); break;
case PPP_FROZEN:
debug("PPP FROZEN"); break;
case TIMEOUT:
debug("TIMEOUT"); break;
case NO_MODEM_RESPONSE:
debug("NO MODEM REPSONSE"); break;
case NO_CARRIER:
debug("NO CARRIER"); break;
case NO_FREE_SOCKET:
debug("NO FREE SOCKET"); break;
case INVALID_SOCKET:
debug("INVALID SOCKET"); break;
case SOCKET_SND_BUSY:
debug("SOCKET SND BUSY"); break;
case SOCKET_NOT_CONNECTED:
debug("SOCKET NOT CONNECTED"); break;
case SOCKET_NOT_ACTIVATED:
debug("SOCKET NOT ACTIVATED"); break;
case NO_BUFFER_SPACE:
debug("NO BUFFER SPACE"); break;
case SOCKET_CLOSE_TIMEOUT:
debug("SOCKET CLOSE TIMEOUT"); break;
case PPP_NOT_CONNECTED:
debug("PPP NOT CONNECTED"); break;
case NO_PPP_DISCONNECT:
debug("NO PPP DISCONNECT"); break;
case MODEM_CONNECTED:
debug("MODEM CONNECTED OK"); break;
case MODEM_BUSY_SIGNAL:
debug("BUSY SIGNAL"); break;
case MODEM_NO_DIALTONE:
debug("NO DIALTONE"); break;
case ID_FAIL:
debug("ID FAIL"); break;
default:
debug("OTHER %U",error); break;
}
}
/********************************************************************
//
// function: tcpip_isr
//
// description: the tcpip_isr if you enable interrupts on the s7600.
// CCS code has s7600 interrupts disabled by default,
// so not only do will you have to enable them but develop this
// ISR as well
//
// input: none
// output: none
// calls:
//
//*******************************************************************/
/*
#int_ext
void tcpip_isr()
{
int8 old_socket;
old_socket=s7600_DMA_Read(SOCKET_SELECT_REG);
//TODO: ISR to check and handle s7600 interrupts
s7600_DMA_Write(SOCKET_SELECT_REG, old_socket);
}
*/
/********************************************************************
//
// function: tcpip_init
//
// description: initializes the tcpip stack. in this case, it initializes the s7600
//
// input: none
// output: MyIpAddr (global)
// calls: s7600_init();
//
//*******************************************************************/
void tcpip_init() {
MyIPAddr=0;
s7600_init();
}
/********************************************************************
//
// function: tcp_connect
//
// description: initializes a tcp data stream between your PIC and a specified host.
// this starts a client connection. if you want to be a server and listen
// to people trying to connect to you then use tcp_listen().
//
// input: ip (ipaddress of host to connect to), portnum (port of host to connect to),
// socket (which one of our sockets to attach to this connection)
// output: s7600_ec (enumerated type that details what our error was)
// calls: s7600_DMA_Write(),s7600_DMA_Read()
//
//*******************************************************************/
s7600_ec tcp_connect(IPAddr ip, int16 portnum, int8 socket)
{
int8 tmp;
int16 to=0;
if (socket == 0xFF) {return(NO_FREE_SOCKET);}
else if (socket > MAX_SOCKET) {return(INVALID_SOCKET);}
s7600_DMA_Write(SOCKET_SELECT_REG, socket);
while ( (to < TCP_TIMEOUT) && (s7600_DMA_Read(SOCKET_STATUS_HIGH) & 0x01) ) //ensure that SND_BUSY is 0 before reset
{
delay_ms(1);
to++;
}
if (to == TCP_TIMEOUT) {return(SOCKET_SND_BUSY);}
s7600_DMA_Write(SOCKET_STATUS_REG, 0x10); //socket reset
delay_ms(10);
s7600_DMA_Write(SOCKET_STATUS_REG, 0x02); //tcp client mode
s7600_DMA_Write(SOCKET_PEER_IP_ADDR+0, make8(ip,0)); //lsb
s7600_DMA_Write(SOCKET_PEER_IP_ADDR+1, make8(ip,1));
s7600_DMA_Write(SOCKET_PEER_IP_ADDR+2, make8(ip,2));
s7600_DMA_Write(SOCKET_PEER_IP_ADDR+3, make8(ip,3)); //msb
s7600_DMA_Write(SOCKET_PEER_PORT+0, make8(portnum,0)); //lsb
s7600_DMA_Write(SOCKET_PEER_PORT+1, make8(portnum,1)); //msb
//if you were to enable interrupts for this socket, you would do it here
s7600_DMA_Write(SOCKET_ACTIVATE_REG, s7600_DMA_Read(SOCKET_ACTIVATE_REG) | (0x01 << socket) ); //activate this socket
to=TCP_CONNECT_TIME;
tmp=0;
while (to && !(tmp & 0x10)) {
delay_ms(1);
to--;
tmp=s7600_DMA_Read(SOCKET_STATUS_REG+1);
}
if ( tmp & 0x10 ) {return(OK);}
else {
s7600_DMA_Write(SOCKET_ACTIVATE_REG, s7600_DMA_Read(SOCKET_ACTIVATE_REG) & ~(0x01 << socket) );
return(SOCKET_NOT_ACTIVATED);
}
}
/********************************************************************
//
// function: tcp_listen
//
// description: opens a server mode tcp connection to the socket and port.
// after a socket is opened as a server you need to use tcp_connectd() to
// see if someone is trying to connect with you.
//
// input: socket (socket to use), port (port to listen on)
// output: s7600_ec (enumerated type that details what our error was)
// calls: s7600_DMA_Read(), s7600_DMA_Write()
//
//*******************************************************************/
s7600_ec tcp_listen(int8 socket, int16 port)
{
int16 to=0;
if (socket == 0xFF) {return(NO_FREE_SOCKET);}
else if (socket > MAX_SOCKET) {return(INVALID_SOCKET);}
s7600_DMA_Write(SOCKET_SELECT_REG, socket);
to=TCP_TIMEOUT;
while ((s7600_DMA_Read(SOCKET_STATUS_HIGH) & 0x01) && to)
{
to--;
delay_ms(1);
}
if (!to) {
return(SOCKET_SND_BUSY);
}
s7600_DMA_Write(SOCKET_STATUS_REG, 0x10); //SOCKET_MASK_RESET
delay_ms(10);
s7600_DMA_Write(SOCKET_STATUS_REG, 0x06); //tcp server mode
s7600_DMA_Write(SOCKET_OUR_PORT+0, make8(port,0)); //lsb
s7600_DMA_Write(SOCKET_OUR_PORT+1, make8(port,1)); //msb
s7600_DMA_Write(SOCKET_ACTIVATE_REG, s7600_DMA_Read(SOCKET_ACTIVATE_REG) | (0x01 << socket) ); //activate socket
return(OK);
}
/********************************************************************
//
// function: tcp_getc
//
// description: works very much like the standard C getc(), except gets data from the TCP/IP
// stack and not rs232. NOTE: this performs no checks as to whether the socket is valid
// or the socket is connected. NOTE: also, this will wait indefinately until data arrives,
// just like getc(). using tcp_kbhit() will check for valid socket, if it is connected, and will
// not wait indefinately. just like kbhit().
//
// input: socket (which socket to get data from)
// output: a character received from the tcpip stack, sent by the host to the PIC
// calls: s7600_DMA_Read(), s7600_DMA_Write()
//
//*******************************************************************/
int8 tcp_getc(int8 socket)
{
int8 c,status;
s7600_DMA_Write(SOCKET_SELECT_REG, socket);
do {
status=s7600_DMA_Read(SOCKET_STATUS_REG);
} while (!(status & 0x10));
c=s7600_DMA_Read(SOCKET_DATA_REG);
return(c);
}
typedef struct {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -