ZG2100 Network interface source
Diff: drv/zg2100/zg_drv.c
- 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