ZG2100 Network interface source

Revision:
0:b802fc31f1db
Child:
1:3a7c15057192
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drv/zg2100/zg_drv.c	Fri Jul 09 15:37:23 2010 +0000
@@ -0,0 +1,332 @@
+
+/*
+Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+ 
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+ 
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+ 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "netCfg.h"
+#if NET_ZG2100
+
+#include "zg_defs.h"
+#include "zg_drv.h"
+#include "zg_com.h"
+
+//#define __DEBUG
+#include "dbg/dbg.h"
+
+#include "mbed.h"
+byte head_buf[ZG_HEAD_BUF_SIZE] ZG_MEM;
+byte fifo_buf[ZG_FIFO_BUF_SIZE] ZG_MEM; //Big buffer used for fifo transfers
+bool int_raised;
+bool mgmt_busy; //Processing a req
+bool tx_pending; //Packet sent but not acked yet
+bool connected; //Connected to a wifi network
+ZG_DATA zg_data; //Container for all data received from the chip
+ZG_DATA_MASK zg_data_mask; //Flags valid data
+uint32_t current_mgmt_param;
+
+//Spi intf, Chip Select pin, Interrupt pin
+zg_err zg_drv_init()
+{
+  word sys_version;
+  int_raised = false;
+  memset((void*)&zg_data, 0, sizeof(ZG_DATA));
+  memset((void*)&zg_data_mask, 0, sizeof(ZG_DATA_MASK));
+  current_mgmt_param = 0;
+  mgmt_busy = false;
+  tx_pending = false;
+  connected = false;
+  
+  //Reset
+  zg_indexed_register_write(ZG_IREG_HW_RST, 0x80FF);
+  zg_indexed_register_write(ZG_IREG_HW_RST, 0x0FFF);
+  
+  DBG("\r\nStarted reset\r\n");
+  
+  while( !(zg_indexed_register_read(ZG_IREG_HW_STATUS) & ZG_HW_STATUS_RESET) )
+  {
+    ;
+  }
+
+  DBG("\r\nStopped\r\n");
+  
+  while( zg_register_read(ZG_REG_F0_ROOM) == 0 )
+  {
+    ;
+  }  
+  
+  DBG("\r\nStarted!\r\n");
+  
+  //Reset OK
+  
+  //Setup interrupts
+  zg_register_write(ZG_REG_INTF, 0);
+  zg_register_write(ZG_REG_INTE, ZG_INT_MASK_F0 | ZG_INT_MASK_F1);
+
+  zg_register_write(ZG_REG_INTF2, 0xff);
+  zg_register_write(ZG_REG_INTE2, 0);
+  
+  //Read firmware version : FIXME
+  
+  zg_register_write(ZG_REG_SYSINFO_INDEX, 0);
+  
+  sys_version = zg_register_read(ZG_REG_SYSINFO) << 8;
+  sys_version |= zg_register_read(ZG_REG_SYSINFO) & 0xFF;
+  
+  DBG("\r\nSystem Version : %04x\r\n", sys_version);
+  
+  DBG("\r\nSetup region\r\n");
+  //Setup region
+  fifo_buf[0] = ZG_REGION;
+  zg_mgmt_set_param(ZG_FIFO_MGMT_PARM_REGION, fifo_buf, 1);
+  
+  while( zg_mgmt_is_busy() )
+  {
+    zg_process();
+  }
+    
+  return ZG_OK;
+}
+
+void zg_on_data_attach( void (*on_data)() )
+{
+
+}
+
+void zg_process() //Must be called regularly by user
+{
+  if( int_raised )
+  {
+    //DBG("\r\nProcessing int\r\n");
+    zg_int_process();
+    int_raised = false;
+  }
+
+}
+
+void zg_int_process()
+{
+  uint32_t int_reg;
+  int fifo;
+  int len;
+  
+  byte type;
+  byte subtype;
+
+  int_reg = zg_register_read(ZG_REG_INTF) & zg_register_read(ZG_REG_INTE); //Read Masked Interrupt reg
+  if( int_reg & ZG_INT_MASK_F0 )
+  {
+    fifo = 0;
+  }
+  else if( int_reg & ZG_INT_MASK_F1 )
+  {
+    fifo = 1;
+  }
+  else
+  {
+    return;
+  }
+  
+  zg_register_write(ZG_REG_INTF, ZG_INT_MASK_F(fifo)); //Select that FIFO ?
+  
+  len = zg_register_read(ZG_REG_F_LEN(fifo)) & 0xFFF; //Only 3 lower level bytes represent length
+  
+  zg_fifo_read(ZG_FIFO_ANY, &type, &subtype, fifo_buf, len);
+  
+  //Dispatch this packet
+  
+  switch( type )
+  {
+  case ZG_FIFO_RD_TXD_ACK:
+    //DBG("\r\nTX ACK\r\n");
+    //Packet has been transmitted, we can send another one
+    tx_pending = false;
+    break;
+  case ZG_FIFO_RD_RXD_AVL:
+    //DBG("\r\nRX AVL\r\n");
+    //Received a packet, process it
+    zg_on_input(fifo_buf, len); //On reception of a ZG frame : convert into Eth frame & call zg_input
+    break;
+  case ZG_FIFO_RD_MGMT_AVL:
+    zg_on_mgmt_avl(subtype, fifo_buf, len);
+    mgmt_busy = false; //We can now do another mgmt req
+    break;
+  case ZG_FIFO_RD_MGMT_EVT:
+    zg_on_mgmt_evt(subtype, fifo_buf, len);
+    break;
+  default:
+    DBG("\r\nInt processed with type %d\r\n", type);
+    //Unknown type
+    return;
+  }
+  
+}
+
+bool zg_mgmt_is_busy()
+{
+  return mgmt_busy;
+}
+
+void zg_mgmt_req(byte subtype, byte* buf, int len, bool close /*= true*/)
+{
+  zg_fifo_write( ZG_FIFO_MGMT, ZG_FIFO_WR_MGMT_REQ, subtype, buf, len, true, close);
+  mgmt_busy = true;
+}
+
+void zg_mgmt_data(byte* buf, int len, bool close /*= true*/)
+{
+  zg_fifo_write( ZG_FIFO_MGMT, ZG_FIFO_WR_MGMT_REQ, 0/*subtype: do not care*/, buf, len, false, close);
+}
+
+void zg_mgmt_get_param(byte param)
+{
+  head_buf[0] = 0;
+  head_buf[1] = param;
+  zg_mgmt_req( ZG_FIFO_MGMT_PARM_GET, head_buf, 2 );
+  current_mgmt_param = param;
+}
+
+void zg_mgmt_set_param(byte param, byte* buf, int len)
+{
+  head_buf[0] = 0;
+  head_buf[1] = param;
+  zg_mgmt_req( ZG_FIFO_MGMT_PARM_SET, head_buf, 2, false );
+  zg_mgmt_data( buf, len );
+  current_mgmt_param = param;
+}
+
+void zg_on_mgmt_avl(byte subtype, byte* buf, int len) //Data is available
+{
+  DBG("\r\nManagement result, subtype %d\r\n", subtype);
+  switch(subtype)
+  {
+  case ZG_FIFO_MGMT_SCAN: //Scan results
+    zg_on_scan_results(buf, len);
+    break;
+    
+  case ZG_FIFO_MGMT_PSK_CALC: //Compute PSK Key
+    zg_on_psk_key(buf, len);
+    break;
+  case ZG_FIFO_MGMT_PMK_KEY: 
+    break;
+  case ZG_FIFO_MGMT_WEP_KEY:
+    break;
+
+  case ZG_FIFO_MGMT_PARM_SET:
+    DBG("\r\nParam set\r\n");
+    break;
+  case ZG_FIFO_MGMT_PARM_GET:
+    zg_on_mgmt_get_param(buf,len);
+    break;
+  case ZG_FIFO_MGMT_ADHOC:
+    break;
+  case ZG_FIFO_MGMT_CONNECT:
+    DBG("\r\nConnect result %d, MAC status is %d\r\n", buf[0], buf[1]);
+    zg_on_connect((zg_err)buf[0]);
+    connected = true;
+    break;  
+  case ZG_FIFO_MGMT_CONN_MGMT:
+    break;
+  default:
+    break;
+  }
+}
+
+void zg_on_mgmt_evt(byte subtype, byte* buf, int len) //Management event
+{
+  DBG("\r\nManagement event, subtype %d\r\n", subtype);
+  switch(subtype)
+  {
+  case ZG_FIFO_MGMT_DISASSOC:
+  case ZG_FIFO_MGMT_DEAUTH:
+    DBG("\r\nDisconnected\r\n");
+    connected = false;
+    break;
+  case ZG_FIFO_MGMT_CONN:
+    DBG("\r\nConnection status %d\r\n", DTOHS( *((word*)&buf[0]) ) );
+    break;
+    
+  default:
+    break;
+  }
+}
+
+void zg_on_mgmt_get_param(byte* buf, int len)
+{
+  if(buf[0] != 1 /*Success*/)
+  {
+    return;
+  }
+  buf+=4; //4-byte header
+  len-=4;
+  switch(current_mgmt_param)
+  {
+  case ZG_FIFO_MGMT_PARM_MACAD: //6 bytes len
+    memcpy((void*)&zg_data.mac_addr, (void*)buf, ZG_MACADDR_LEN);
+    zg_data_mask.mac_addr = true;
+    DBG("\r\nHW Addr is : %02x:%02x:%02x:%02x:%02x:%02x.\r\n", 
+    zg_data.mac_addr[0], zg_data.mac_addr[1], zg_data.mac_addr[2],
+    zg_data.mac_addr[3], zg_data.mac_addr[4], zg_data.mac_addr[5]);
+    break;
+  case ZG_FIFO_MGMT_PARM_SYSV: //2 bytes len
+    memcpy((void*)&zg_data.sys_version, (void*)buf, 2);
+    DBG("\r\nSys version: ROM: %02x; Patch: %02x\r\n",
+    zg_data.sys_version.rom, zg_data.sys_version.revision);
+    zg_data_mask.sys_version = true;  
+    break;
+  case ZG_FIFO_MGMT_PARM_REGION:
+    DBG("\r\nRegion %d\r\n", buf[0]);
+    break;
+  default:
+    break;
+  } 
+  current_mgmt_param = 0;
+}
+
+//uint32_t zg_fifo_room();
+
+void zg_on_int() //On data available interrupt
+{
+  int_raised = true;
+}
+
+//Useful to be split in several function because Lwip stores buffers in chunks
+void zg_send_start()
+{
+  tx_pending = true;
+  zg_fifo_write( ZG_FIFO_DATA, ZG_FIFO_WR_TXD_REQ, ZG_FIFO_TXD_STD, NULL, 0, true, false ); //Open fifo but does not close it
+}
+
+void zg_send(byte* buf, int len)
+{
+  zg_fifo_write( ZG_FIFO_DATA, ZG_FIFO_WR_TXD_REQ, ZG_FIFO_TXD_STD, buf, len, false, false );
+}
+
+void zg_send_end()
+{
+  zg_fifo_write( ZG_FIFO_DATA, ZG_FIFO_WR_TXD_REQ, ZG_FIFO_TXD_STD, NULL, 0, false, true ); //Close fifo
+}
+
+bool zg_send_is_busy()
+{
+  return tx_pending;
+}
+
+#endif